mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-29 20:30:35 +00:00
ALSA: firewire-motu: enable to read transaction cache via hwdep interface
MOTU FireWire series can transfer messages to registered address. These messages are transferred for the status of internal clock synchronization just after starting streams. When the synchronization is stable, it's 0x01ffffff. Else, it's 0x05ffffff. This commit adds a functionality for user space applications to receive content of the message. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
71c3797779
commit
5aaab1bf37
3 changed files with 35 additions and 2 deletions
|
@ -10,6 +10,7 @@
|
||||||
#define SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION 0xd1ce004e
|
#define SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION 0xd1ce004e
|
||||||
#define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475
|
#define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475
|
||||||
#define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c
|
#define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c
|
||||||
|
#define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479
|
||||||
|
|
||||||
struct snd_firewire_event_common {
|
struct snd_firewire_event_common {
|
||||||
unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
|
unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
|
||||||
|
@ -46,12 +47,18 @@ struct snd_firewire_event_digi00x_message {
|
||||||
__u32 message; /* Digi00x-specific message */
|
__u32 message; /* Digi00x-specific message */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct snd_firewire_event_motu_notification {
|
||||||
|
unsigned int type;
|
||||||
|
__u32 message; /* MOTU-specific bits. */
|
||||||
|
};
|
||||||
|
|
||||||
union snd_firewire_event {
|
union snd_firewire_event {
|
||||||
struct snd_firewire_event_common common;
|
struct snd_firewire_event_common common;
|
||||||
struct snd_firewire_event_lock_status lock_status;
|
struct snd_firewire_event_lock_status lock_status;
|
||||||
struct snd_firewire_event_dice_notification dice_notification;
|
struct snd_firewire_event_dice_notification dice_notification;
|
||||||
struct snd_firewire_event_efw_response efw_response;
|
struct snd_firewire_event_efw_response efw_response;
|
||||||
struct snd_firewire_event_digi00x_message digi00x_message;
|
struct snd_firewire_event_digi00x_message digi00x_message;
|
||||||
|
struct snd_firewire_event_motu_notification motu_notification;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
|
||||||
|
|
||||||
spin_lock_irq(&motu->lock);
|
spin_lock_irq(&motu->lock);
|
||||||
|
|
||||||
while (!motu->dev_lock_changed) {
|
while (!motu->dev_lock_changed && motu->msg == 0) {
|
||||||
prepare_to_wait(&motu->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
|
prepare_to_wait(&motu->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
|
||||||
spin_unlock_irq(&motu->lock);
|
spin_unlock_irq(&motu->lock);
|
||||||
schedule();
|
schedule();
|
||||||
|
@ -43,6 +43,12 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
|
||||||
motu->dev_lock_changed = false;
|
motu->dev_lock_changed = false;
|
||||||
|
|
||||||
count = min_t(long, count, sizeof(event.lock_status));
|
count = min_t(long, count, sizeof(event.lock_status));
|
||||||
|
} else {
|
||||||
|
event.motu_notification.type = SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION;
|
||||||
|
event.motu_notification.message = motu->msg;
|
||||||
|
motu->msg = 0;
|
||||||
|
|
||||||
|
count = min_t(long, count, sizeof(event.motu_notification));
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irq(&motu->lock);
|
spin_unlock_irq(&motu->lock);
|
||||||
|
@ -62,7 +68,7 @@ static unsigned int hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
|
||||||
poll_wait(file, &motu->hwdep_wait, wait);
|
poll_wait(file, &motu->hwdep_wait, wait);
|
||||||
|
|
||||||
spin_lock_irq(&motu->lock);
|
spin_lock_irq(&motu->lock);
|
||||||
if (motu->dev_lock_changed)
|
if (motu->dev_lock_changed || motu->msg)
|
||||||
events = POLLIN | POLLRDNORM;
|
events = POLLIN | POLLRDNORM;
|
||||||
else
|
else
|
||||||
events = 0;
|
events = 0;
|
||||||
|
|
|
@ -50,7 +50,27 @@ static void handle_message(struct fw_card *card, struct fw_request *request,
|
||||||
int generation, unsigned long long offset,
|
int generation, unsigned long long offset,
|
||||||
void *data, size_t length, void *callback_data)
|
void *data, size_t length, void *callback_data)
|
||||||
{
|
{
|
||||||
|
struct snd_motu *motu = callback_data;
|
||||||
|
__be32 *buf = (__be32 *)data;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
|
||||||
|
fw_send_response(card, request, RCODE_COMPLETE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != motu->async_handler.offset || length != 4) {
|
||||||
|
fw_send_response(card, request, RCODE_ADDRESS_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&motu->lock, flags);
|
||||||
|
motu->msg = be32_to_cpu(*buf);
|
||||||
|
spin_unlock_irqrestore(&motu->lock, flags);
|
||||||
|
|
||||||
fw_send_response(card, request, RCODE_COMPLETE);
|
fw_send_response(card, request, RCODE_COMPLETE);
|
||||||
|
|
||||||
|
wake_up(&motu->hwdep_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_motu_transaction_reregister(struct snd_motu *motu)
|
int snd_motu_transaction_reregister(struct snd_motu *motu)
|
||||||
|
|
Loading…
Reference in a new issue