summaryrefslogtreecommitdiffstats
path: root/sound/firewire/fireworks/fireworks.c
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-04-25 22:45:01 +0900
committerTakashi Iwai <tiwai@suse.de>2014-05-26 14:24:03 +0200
commitbde8a8f23bbe6db51fa4e81644273af18fef3d7a (patch)
tree92ea0fbb1023bda284156ac561640f4502132409 /sound/firewire/fireworks/fireworks.c
parentb5b04336015e76eb52ffc188e16c9cee01821c7c (diff)
downloadlinux-bde8a8f23bbe6db51fa4e81644273af18fef3d7a.tar.bz2
ALSA: fireworks: Add transaction and some commands
Fireworks uses own command and response. This commit adds functionality to transact and adds some commands required for sound card instance and kernel streaming. There are two ways to deliver substance of this transaction: 1.AV/C vendor dependent command for command/response 2.Async transaction to specific addresses for command/response By way 1, I confirm AudioFire12 cannot correctly response to some commands with firmware version 5.0 or later. This is also confirmed by FFADO. So this driver implement way 2. The address for response gives an issue. When this driver allocate own callback function into the address, then no one can allocate its own callback function. This situation is not good for applications in user-land. This issue is solved in later commit. I note there is a command to change the address for response if the device supports. But this driver uses default value. So users should not execute this command as long as hoping this driver works correctly. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/fireworks/fireworks.c')
-rw-r--r--sound/firewire/fireworks/fireworks.c69
1 files changed, 63 insertions, 6 deletions
diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c
index ad719a1d5353..6fa3a5d725d5 100644
--- a/sound/firewire/fireworks/fireworks.c
+++ b/sound/firewire/fireworks/fireworks.c
@@ -59,6 +59,50 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS);
/* unknown as product */
#define MODEL_GIBSON_GOLDTOP 0x00afb9
+/* part of hardware capability flags */
+#define FLAG_RESP_ADDR_CHANGABLE 0
+
+static int
+get_hardware_info(struct snd_efw *efw)
+{
+ struct fw_device *fw_dev = fw_parent_device(efw->unit);
+ struct snd_efw_hwinfo *hwinfo;
+ char version[12] = {0};
+ int err;
+
+ hwinfo = kzalloc(sizeof(struct snd_efw_hwinfo), GFP_KERNEL);
+ if (hwinfo == NULL)
+ return -ENOMEM;
+
+ err = snd_efw_command_get_hwinfo(efw, hwinfo);
+ if (err < 0)
+ goto end;
+
+ /* firmware version for communication chipset */
+ snprintf(version, sizeof(version), "%u.%u",
+ (hwinfo->arm_version >> 24) & 0xff,
+ (hwinfo->arm_version >> 16) & 0xff);
+ if (err < 0)
+ goto end;
+
+ strcpy(efw->card->driver, "Fireworks");
+ strcpy(efw->card->shortname, hwinfo->model_name);
+ strcpy(efw->card->mixername, hwinfo->model_name);
+ snprintf(efw->card->longname, sizeof(efw->card->longname),
+ "%s %s v%s, GUID %08x%08x at %s, S%d",
+ hwinfo->vendor_name, hwinfo->model_name, version,
+ hwinfo->guid_hi, hwinfo->guid_lo,
+ dev_name(&efw->unit->device), 100 << fw_dev->max_speed);
+ if (err < 0)
+ goto end;
+
+ if (hwinfo->flags & BIT(FLAG_RESP_ADDR_CHANGABLE))
+ efw->resp_addr_changable = true;
+end:
+ kfree(hwinfo);
+ return err;
+}
+
static void
efw_card_free(struct snd_card *card)
{
@@ -107,14 +151,14 @@ efw_probe(struct fw_unit *unit,
mutex_init(&efw->mutex);
spin_lock_init(&efw->lock);
- strcpy(efw->card->driver, "Fireworks");
- strcpy(efw->card->shortname, efw->card->driver);
- strcpy(efw->card->longname, efw->card->driver);
- strcpy(efw->card->mixername, efw->card->driver);
+ err = get_hardware_info(efw);
+ if (err < 0)
+ goto error;
err = snd_card_register(card);
if (err < 0)
goto error;
+
dev_set_drvdata(&unit->device, efw);
end:
mutex_unlock(&devices_mutex);
@@ -127,7 +171,8 @@ error:
static void efw_update(struct fw_unit *unit)
{
- return;
+ struct snd_efw *efw = dev_get_drvdata(&unit->device);
+ snd_efw_transaction_bus_reset(efw->unit);
}
static void efw_remove(struct fw_unit *unit)
@@ -169,11 +214,23 @@ static struct fw_driver efw_driver = {
static int __init snd_efw_init(void)
{
- return driver_register(&efw_driver.driver);
+ int err;
+
+ err = snd_efw_transaction_register();
+ if (err < 0)
+ goto end;
+
+ err = driver_register(&efw_driver.driver);
+ if (err < 0)
+ snd_efw_transaction_unregister();
+
+end:
+ return err;
}
static void __exit snd_efw_exit(void)
{
+ snd_efw_transaction_unregister();
driver_unregister(&efw_driver.driver);
mutex_destroy(&devices_mutex);
}