11a4e39c2STakashi Sakamoto /* 21a4e39c2STakashi Sakamoto * oxfw.c - a part of driver for OXFW970/971 based devices 31a4e39c2STakashi Sakamoto * 41a4e39c2STakashi Sakamoto * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 51a4e39c2STakashi Sakamoto * Licensed under the terms of the GNU General Public License, version 2. 61a4e39c2STakashi Sakamoto */ 71a4e39c2STakashi Sakamoto 8e2786ca6STakashi Sakamoto #include "oxfw.h" 91a4e39c2STakashi Sakamoto 101a4e39c2STakashi Sakamoto #define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000) 111a4e39c2STakashi Sakamoto /* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */ 121a4e39c2STakashi Sakamoto 131a4e39c2STakashi Sakamoto #define OXFORD_HARDWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x90020) 141a4e39c2STakashi Sakamoto #define OXFORD_HARDWARE_ID_OXFW970 0x39443841 151a4e39c2STakashi Sakamoto #define OXFORD_HARDWARE_ID_OXFW971 0x39373100 161a4e39c2STakashi Sakamoto 17ec4dba50STakashi Sakamoto #define VENDOR_LOUD 0x000ff2 181a4e39c2STakashi Sakamoto #define VENDOR_GRIFFIN 0x001292 19ec4dba50STakashi Sakamoto #define VENDOR_BEHRINGER 0x001564 201a4e39c2STakashi Sakamoto #define VENDOR_LACIE 0x00d04b 211a4e39c2STakashi Sakamoto 221a4e39c2STakashi Sakamoto #define SPECIFIER_1394TA 0x00a02d 231a4e39c2STakashi Sakamoto #define VERSION_AVC 0x010001 241a4e39c2STakashi Sakamoto 251a4e39c2STakashi Sakamoto MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver"); 261a4e39c2STakashi Sakamoto MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 271a4e39c2STakashi Sakamoto MODULE_LICENSE("GPL v2"); 281a4e39c2STakashi Sakamoto MODULE_ALIAS("snd-firewire-speakers"); 291a4e39c2STakashi Sakamoto 30ec4dba50STakashi Sakamoto static bool detect_loud_models(struct fw_unit *unit) 31ec4dba50STakashi Sakamoto { 32ec4dba50STakashi Sakamoto const char *const models[] = { 33ec4dba50STakashi Sakamoto "Onyxi", 34ec4dba50STakashi Sakamoto "Onyx-i", 35ec4dba50STakashi Sakamoto "d.Pro", 36ec4dba50STakashi Sakamoto "Mackie Onyx Satellite", 37ec4dba50STakashi Sakamoto "Tapco LINK.firewire 4x6", 38ec4dba50STakashi Sakamoto "U.420"}; 39ec4dba50STakashi Sakamoto char model[32]; 40ec4dba50STakashi Sakamoto unsigned int i; 41ec4dba50STakashi Sakamoto int err; 42ec4dba50STakashi Sakamoto 43ec4dba50STakashi Sakamoto err = fw_csr_string(unit->directory, CSR_MODEL, 44ec4dba50STakashi Sakamoto model, sizeof(model)); 45ec4dba50STakashi Sakamoto if (err < 0) 46ec4dba50STakashi Sakamoto return err; 47ec4dba50STakashi Sakamoto 48ec4dba50STakashi Sakamoto for (i = 0; i < ARRAY_SIZE(models); i++) { 49ec4dba50STakashi Sakamoto if (strcmp(models[i], model) == 0) 50ec4dba50STakashi Sakamoto break; 51ec4dba50STakashi Sakamoto } 52ec4dba50STakashi Sakamoto 53ec4dba50STakashi Sakamoto return (i < ARRAY_SIZE(models)); 54ec4dba50STakashi Sakamoto } 55ec4dba50STakashi Sakamoto 56fec7b753STakashi Sakamoto static int name_card(struct snd_oxfw *oxfw) 571a4e39c2STakashi Sakamoto { 58fec7b753STakashi Sakamoto struct fw_device *fw_dev = fw_parent_device(oxfw->unit); 59ec4dba50STakashi Sakamoto char vendor[24]; 60ec4dba50STakashi Sakamoto char model[32]; 61fec7b753STakashi Sakamoto const char *d, *v, *m; 62fec7b753STakashi Sakamoto u32 firmware; 631a4e39c2STakashi Sakamoto int err; 641a4e39c2STakashi Sakamoto 65ec4dba50STakashi Sakamoto /* get vendor name from root directory */ 66ec4dba50STakashi Sakamoto err = fw_csr_string(fw_dev->config_rom + 5, CSR_VENDOR, 67ec4dba50STakashi Sakamoto vendor, sizeof(vendor)); 68ec4dba50STakashi Sakamoto if (err < 0) 69ec4dba50STakashi Sakamoto goto end; 70ec4dba50STakashi Sakamoto 71ec4dba50STakashi Sakamoto /* get model name from unit directory */ 72ec4dba50STakashi Sakamoto err = fw_csr_string(oxfw->unit->directory, CSR_MODEL, 73ec4dba50STakashi Sakamoto model, sizeof(model)); 74ec4dba50STakashi Sakamoto if (err < 0) 75ec4dba50STakashi Sakamoto goto end; 76ec4dba50STakashi Sakamoto 77fec7b753STakashi Sakamoto err = snd_fw_transaction(oxfw->unit, TCODE_READ_QUADLET_REQUEST, 78fec7b753STakashi Sakamoto OXFORD_FIRMWARE_ID_ADDRESS, &firmware, 4, 0); 79fec7b753STakashi Sakamoto if (err < 0) 80fec7b753STakashi Sakamoto goto end; 81fec7b753STakashi Sakamoto be32_to_cpus(&firmware); 82fec7b753STakashi Sakamoto 83ec4dba50STakashi Sakamoto /* to apply card definitions */ 84ec4dba50STakashi Sakamoto if (oxfw->device_info) { 85fec7b753STakashi Sakamoto d = oxfw->device_info->driver_name; 86fec7b753STakashi Sakamoto v = oxfw->device_info->vendor_name; 87fec7b753STakashi Sakamoto m = oxfw->device_info->model_name; 88ec4dba50STakashi Sakamoto } else { 89ec4dba50STakashi Sakamoto d = "OXFW"; 90ec4dba50STakashi Sakamoto v = vendor; 91ec4dba50STakashi Sakamoto m = model; 92ec4dba50STakashi Sakamoto } 93fec7b753STakashi Sakamoto 94fec7b753STakashi Sakamoto strcpy(oxfw->card->driver, d); 95fec7b753STakashi Sakamoto strcpy(oxfw->card->mixername, m); 96fec7b753STakashi Sakamoto strcpy(oxfw->card->shortname, m); 97fec7b753STakashi Sakamoto 98fec7b753STakashi Sakamoto snprintf(oxfw->card->longname, sizeof(oxfw->card->longname), 99fec7b753STakashi Sakamoto "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d", 100fec7b753STakashi Sakamoto v, m, firmware >> 20, firmware & 0xffff, 101fec7b753STakashi Sakamoto fw_dev->config_rom[3], fw_dev->config_rom[4], 102fec7b753STakashi Sakamoto dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed); 103fec7b753STakashi Sakamoto end: 104fec7b753STakashi Sakamoto return err; 1051a4e39c2STakashi Sakamoto } 1061a4e39c2STakashi Sakamoto 1071a4e39c2STakashi Sakamoto static void oxfw_card_free(struct snd_card *card) 1081a4e39c2STakashi Sakamoto { 1091a4e39c2STakashi Sakamoto struct snd_oxfw *oxfw = card->private_data; 1105cd1d3f4STakashi Sakamoto unsigned int i; 1115cd1d3f4STakashi Sakamoto 112b0ac0009STakashi Sakamoto for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { 113b0ac0009STakashi Sakamoto kfree(oxfw->tx_stream_formats[i]); 1145cd1d3f4STakashi Sakamoto kfree(oxfw->rx_stream_formats[i]); 115b0ac0009STakashi Sakamoto } 1161a4e39c2STakashi Sakamoto 1171a4e39c2STakashi Sakamoto mutex_destroy(&oxfw->mutex); 1181a4e39c2STakashi Sakamoto } 1191a4e39c2STakashi Sakamoto 1201a4e39c2STakashi Sakamoto static int oxfw_probe(struct fw_unit *unit, 1211a4e39c2STakashi Sakamoto const struct ieee1394_device_id *id) 1221a4e39c2STakashi Sakamoto { 1231a4e39c2STakashi Sakamoto struct snd_card *card; 1241a4e39c2STakashi Sakamoto struct snd_oxfw *oxfw; 1251a4e39c2STakashi Sakamoto int err; 1261a4e39c2STakashi Sakamoto 127ec4dba50STakashi Sakamoto if ((id->vendor_id == VENDOR_LOUD) && !detect_loud_models(unit)) 128ec4dba50STakashi Sakamoto return -ENODEV; 129ec4dba50STakashi Sakamoto 1301a4e39c2STakashi Sakamoto err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, 1311a4e39c2STakashi Sakamoto sizeof(*oxfw), &card); 1321a4e39c2STakashi Sakamoto if (err < 0) 1331a4e39c2STakashi Sakamoto return err; 1341a4e39c2STakashi Sakamoto 135e2786ca6STakashi Sakamoto card->private_free = oxfw_card_free; 1361a4e39c2STakashi Sakamoto oxfw = card->private_data; 1371a4e39c2STakashi Sakamoto oxfw->card = card; 1381a4e39c2STakashi Sakamoto mutex_init(&oxfw->mutex); 139e2786ca6STakashi Sakamoto oxfw->unit = unit; 1401a4e39c2STakashi Sakamoto oxfw->device_info = (const struct device_info *)id->driver_data; 1411a4e39c2STakashi Sakamoto 1425cd1d3f4STakashi Sakamoto err = snd_oxfw_stream_discover(oxfw); 1435cd1d3f4STakashi Sakamoto if (err < 0) 1445cd1d3f4STakashi Sakamoto goto error; 1455cd1d3f4STakashi Sakamoto 146fec7b753STakashi Sakamoto err = name_card(oxfw); 147fec7b753STakashi Sakamoto if (err < 0) 148fec7b753STakashi Sakamoto goto error; 1491a4e39c2STakashi Sakamoto 1503713d93aSTakashi Sakamoto err = snd_oxfw_create_pcm(oxfw); 1511a4e39c2STakashi Sakamoto if (err < 0) 1521a4e39c2STakashi Sakamoto goto error; 1531a4e39c2STakashi Sakamoto 154ec4dba50STakashi Sakamoto if (oxfw->device_info) { 15531514bfbSTakashi Sakamoto err = snd_oxfw_create_mixer(oxfw); 1561a4e39c2STakashi Sakamoto if (err < 0) 1571a4e39c2STakashi Sakamoto goto error; 158ec4dba50STakashi Sakamoto } 1591a4e39c2STakashi Sakamoto 1603c96101fSTakashi Sakamoto snd_oxfw_proc_init(oxfw); 1613c96101fSTakashi Sakamoto 162b0ac0009STakashi Sakamoto err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->rx_stream); 1631a4e39c2STakashi Sakamoto if (err < 0) 1641a4e39c2STakashi Sakamoto goto error; 165b0ac0009STakashi Sakamoto if (oxfw->has_output) { 166b0ac0009STakashi Sakamoto err = snd_oxfw_stream_init_simplex(oxfw, &oxfw->tx_stream); 167b0ac0009STakashi Sakamoto if (err < 0) 168b0ac0009STakashi Sakamoto goto error; 169b0ac0009STakashi Sakamoto } 1701a4e39c2STakashi Sakamoto 171e2786ca6STakashi Sakamoto err = snd_card_register(card); 172e2786ca6STakashi Sakamoto if (err < 0) { 173b0ac0009STakashi Sakamoto snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); 174b0ac0009STakashi Sakamoto if (oxfw->has_output) 175b0ac0009STakashi Sakamoto snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); 176e2786ca6STakashi Sakamoto goto error; 177e2786ca6STakashi Sakamoto } 1781a4e39c2STakashi Sakamoto dev_set_drvdata(&unit->device, oxfw); 1791a4e39c2STakashi Sakamoto 1801a4e39c2STakashi Sakamoto return 0; 1811a4e39c2STakashi Sakamoto error: 1821a4e39c2STakashi Sakamoto snd_card_free(card); 1831a4e39c2STakashi Sakamoto return err; 1841a4e39c2STakashi Sakamoto } 1851a4e39c2STakashi Sakamoto 1861a4e39c2STakashi Sakamoto static void oxfw_bus_reset(struct fw_unit *unit) 1871a4e39c2STakashi Sakamoto { 1881a4e39c2STakashi Sakamoto struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); 1891a4e39c2STakashi Sakamoto 1901a4e39c2STakashi Sakamoto fcp_bus_reset(oxfw->unit); 1911a4e39c2STakashi Sakamoto 1921a4e39c2STakashi Sakamoto mutex_lock(&oxfw->mutex); 193b0ac0009STakashi Sakamoto 194b0ac0009STakashi Sakamoto snd_oxfw_stream_update_simplex(oxfw, &oxfw->rx_stream); 195b0ac0009STakashi Sakamoto if (oxfw->has_output) 196b0ac0009STakashi Sakamoto snd_oxfw_stream_update_simplex(oxfw, &oxfw->tx_stream); 197b0ac0009STakashi Sakamoto 1981a4e39c2STakashi Sakamoto mutex_unlock(&oxfw->mutex); 1991a4e39c2STakashi Sakamoto } 2001a4e39c2STakashi Sakamoto 2011a4e39c2STakashi Sakamoto static void oxfw_remove(struct fw_unit *unit) 2021a4e39c2STakashi Sakamoto { 2031a4e39c2STakashi Sakamoto struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); 2041a4e39c2STakashi Sakamoto 2051a4e39c2STakashi Sakamoto snd_card_disconnect(oxfw->card); 2061a4e39c2STakashi Sakamoto 207b0ac0009STakashi Sakamoto snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); 208b0ac0009STakashi Sakamoto if (oxfw->has_output) 209b0ac0009STakashi Sakamoto snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); 2101a4e39c2STakashi Sakamoto 2111a4e39c2STakashi Sakamoto snd_card_free_when_closed(oxfw->card); 2121a4e39c2STakashi Sakamoto } 2131a4e39c2STakashi Sakamoto 2141a4e39c2STakashi Sakamoto static const struct device_info griffin_firewave = { 2151a4e39c2STakashi Sakamoto .driver_name = "FireWave", 216fec7b753STakashi Sakamoto .vendor_name = "Griffin", 217fec7b753STakashi Sakamoto .model_name = "FireWave", 2181a4e39c2STakashi Sakamoto .mixer_channels = 6, 2191a4e39c2STakashi Sakamoto .mute_fb_id = 0x01, 2201a4e39c2STakashi Sakamoto .volume_fb_id = 0x02, 2211a4e39c2STakashi Sakamoto }; 2221a4e39c2STakashi Sakamoto 2231a4e39c2STakashi Sakamoto static const struct device_info lacie_speakers = { 2241a4e39c2STakashi Sakamoto .driver_name = "FWSpeakers", 225fec7b753STakashi Sakamoto .vendor_name = "LaCie", 226fec7b753STakashi Sakamoto .model_name = "FireWire Speakers", 2271a4e39c2STakashi Sakamoto .mixer_channels = 1, 2281a4e39c2STakashi Sakamoto .mute_fb_id = 0x01, 2291a4e39c2STakashi Sakamoto .volume_fb_id = 0x01, 2301a4e39c2STakashi Sakamoto }; 2311a4e39c2STakashi Sakamoto 2321a4e39c2STakashi Sakamoto static const struct ieee1394_device_id oxfw_id_table[] = { 2331a4e39c2STakashi Sakamoto { 2341a4e39c2STakashi Sakamoto .match_flags = IEEE1394_MATCH_VENDOR_ID | 2351a4e39c2STakashi Sakamoto IEEE1394_MATCH_MODEL_ID | 2361a4e39c2STakashi Sakamoto IEEE1394_MATCH_SPECIFIER_ID | 2371a4e39c2STakashi Sakamoto IEEE1394_MATCH_VERSION, 2381a4e39c2STakashi Sakamoto .vendor_id = VENDOR_GRIFFIN, 2391a4e39c2STakashi Sakamoto .model_id = 0x00f970, 2401a4e39c2STakashi Sakamoto .specifier_id = SPECIFIER_1394TA, 2411a4e39c2STakashi Sakamoto .version = VERSION_AVC, 2421a4e39c2STakashi Sakamoto .driver_data = (kernel_ulong_t)&griffin_firewave, 2431a4e39c2STakashi Sakamoto }, 2441a4e39c2STakashi Sakamoto { 2451a4e39c2STakashi Sakamoto .match_flags = IEEE1394_MATCH_VENDOR_ID | 2461a4e39c2STakashi Sakamoto IEEE1394_MATCH_MODEL_ID | 2471a4e39c2STakashi Sakamoto IEEE1394_MATCH_SPECIFIER_ID | 2481a4e39c2STakashi Sakamoto IEEE1394_MATCH_VERSION, 2491a4e39c2STakashi Sakamoto .vendor_id = VENDOR_LACIE, 2501a4e39c2STakashi Sakamoto .model_id = 0x00f970, 2511a4e39c2STakashi Sakamoto .specifier_id = SPECIFIER_1394TA, 2521a4e39c2STakashi Sakamoto .version = VERSION_AVC, 2531a4e39c2STakashi Sakamoto .driver_data = (kernel_ulong_t)&lacie_speakers, 2541a4e39c2STakashi Sakamoto }, 255ec4dba50STakashi Sakamoto /* Behringer,F-Control Audio 202 */ 256ec4dba50STakashi Sakamoto { 257ec4dba50STakashi Sakamoto .match_flags = IEEE1394_MATCH_VENDOR_ID | 258ec4dba50STakashi Sakamoto IEEE1394_MATCH_MODEL_ID, 259ec4dba50STakashi Sakamoto .vendor_id = VENDOR_BEHRINGER, 260ec4dba50STakashi Sakamoto .model_id = 0x00fc22, 261ec4dba50STakashi Sakamoto }, 262ec4dba50STakashi Sakamoto /* 263ec4dba50STakashi Sakamoto * Any Mackie(Loud) models (name string/model id): 264ec4dba50STakashi Sakamoto * Onyx-i series (former models): 0x081216 265ec4dba50STakashi Sakamoto * Mackie Onyx Satellite: 0x00200f 266ec4dba50STakashi Sakamoto * Tapco LINK.firewire 4x6: 0x000460 267ec4dba50STakashi Sakamoto * d.2 pro: Unknown 268ec4dba50STakashi Sakamoto * d.4 pro: Unknown 269ec4dba50STakashi Sakamoto * U.420: Unknown 270ec4dba50STakashi Sakamoto * U.420d: Unknown 271ec4dba50STakashi Sakamoto */ 272ec4dba50STakashi Sakamoto { 273ec4dba50STakashi Sakamoto .match_flags = IEEE1394_MATCH_VENDOR_ID | 274ec4dba50STakashi Sakamoto IEEE1394_MATCH_SPECIFIER_ID | 275ec4dba50STakashi Sakamoto IEEE1394_MATCH_VERSION, 276ec4dba50STakashi Sakamoto .vendor_id = VENDOR_LOUD, 277ec4dba50STakashi Sakamoto .specifier_id = SPECIFIER_1394TA, 278ec4dba50STakashi Sakamoto .version = VERSION_AVC, 279ec4dba50STakashi Sakamoto }, 2801a4e39c2STakashi Sakamoto { } 2811a4e39c2STakashi Sakamoto }; 2821a4e39c2STakashi Sakamoto MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table); 2831a4e39c2STakashi Sakamoto 2841a4e39c2STakashi Sakamoto static struct fw_driver oxfw_driver = { 2851a4e39c2STakashi Sakamoto .driver = { 2861a4e39c2STakashi Sakamoto .owner = THIS_MODULE, 2871a4e39c2STakashi Sakamoto .name = KBUILD_MODNAME, 2881a4e39c2STakashi Sakamoto .bus = &fw_bus_type, 2891a4e39c2STakashi Sakamoto }, 2901a4e39c2STakashi Sakamoto .probe = oxfw_probe, 2911a4e39c2STakashi Sakamoto .update = oxfw_bus_reset, 2921a4e39c2STakashi Sakamoto .remove = oxfw_remove, 2931a4e39c2STakashi Sakamoto .id_table = oxfw_id_table, 2941a4e39c2STakashi Sakamoto }; 2951a4e39c2STakashi Sakamoto 2961a4e39c2STakashi Sakamoto static int __init snd_oxfw_init(void) 2971a4e39c2STakashi Sakamoto { 2981a4e39c2STakashi Sakamoto return driver_register(&oxfw_driver.driver); 2991a4e39c2STakashi Sakamoto } 3001a4e39c2STakashi Sakamoto 3011a4e39c2STakashi Sakamoto static void __exit snd_oxfw_exit(void) 3021a4e39c2STakashi Sakamoto { 3031a4e39c2STakashi Sakamoto driver_unregister(&oxfw_driver.driver); 3041a4e39c2STakashi Sakamoto } 3051a4e39c2STakashi Sakamoto 3061a4e39c2STakashi Sakamoto module_init(snd_oxfw_init); 3071a4e39c2STakashi Sakamoto module_exit(snd_oxfw_exit); 308