0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "motu.h"
0010
0011 #define SND_MOTU_ADDR_BASE 0xfffff0000000ULL
0012 #define ASYNC_ADDR_HI 0x0b04
0013 #define ASYNC_ADDR_LO 0x0b08
0014
0015 int snd_motu_transaction_read(struct snd_motu *motu, u32 offset, __be32 *reg,
0016 size_t size)
0017 {
0018 int tcode;
0019
0020 if (size % sizeof(__be32) > 0 || size <= 0)
0021 return -EINVAL;
0022 if (size == sizeof(__be32))
0023 tcode = TCODE_READ_QUADLET_REQUEST;
0024 else
0025 tcode = TCODE_READ_BLOCK_REQUEST;
0026
0027 return snd_fw_transaction(motu->unit, tcode,
0028 SND_MOTU_ADDR_BASE + offset, reg, size, 0);
0029 }
0030
0031 int snd_motu_transaction_write(struct snd_motu *motu, u32 offset, __be32 *reg,
0032 size_t size)
0033 {
0034 int tcode;
0035
0036 if (size % sizeof(__be32) > 0 || size <= 0)
0037 return -EINVAL;
0038 if (size == sizeof(__be32))
0039 tcode = TCODE_WRITE_QUADLET_REQUEST;
0040 else
0041 tcode = TCODE_WRITE_BLOCK_REQUEST;
0042
0043 return snd_fw_transaction(motu->unit, tcode,
0044 SND_MOTU_ADDR_BASE + offset, reg, size, 0);
0045 }
0046
0047 static void handle_message(struct fw_card *card, struct fw_request *request,
0048 int tcode, int destination, int source,
0049 int generation, unsigned long long offset,
0050 void *data, size_t length, void *callback_data)
0051 {
0052 struct snd_motu *motu = callback_data;
0053 __be32 *buf = (__be32 *)data;
0054 unsigned long flags;
0055
0056 if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
0057 fw_send_response(card, request, RCODE_COMPLETE);
0058 return;
0059 }
0060
0061 if (offset != motu->async_handler.offset || length != 4) {
0062 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
0063 return;
0064 }
0065
0066 spin_lock_irqsave(&motu->lock, flags);
0067 motu->msg = be32_to_cpu(*buf);
0068 spin_unlock_irqrestore(&motu->lock, flags);
0069
0070 fw_send_response(card, request, RCODE_COMPLETE);
0071
0072 wake_up(&motu->hwdep_wait);
0073 }
0074
0075 int snd_motu_transaction_reregister(struct snd_motu *motu)
0076 {
0077 struct fw_device *device = fw_parent_device(motu->unit);
0078 __be32 data;
0079 int err;
0080
0081 if (motu->async_handler.callback_data == NULL)
0082 return -EINVAL;
0083
0084
0085 data = cpu_to_be32((device->card->node_id << 16) |
0086 (motu->async_handler.offset >> 32));
0087 err = snd_motu_transaction_write(motu, ASYNC_ADDR_HI, &data,
0088 sizeof(data));
0089 if (err < 0)
0090 return err;
0091
0092 data = cpu_to_be32(motu->async_handler.offset);
0093 return snd_motu_transaction_write(motu, ASYNC_ADDR_LO, &data,
0094 sizeof(data));
0095 }
0096
0097 int snd_motu_transaction_register(struct snd_motu *motu)
0098 {
0099 static const struct fw_address_region resp_register_region = {
0100 .start = 0xffffe0000000ull,
0101 .end = 0xffffe000ffffull,
0102 };
0103 int err;
0104
0105
0106 motu->async_handler.length = 4;
0107 motu->async_handler.address_callback = handle_message;
0108 motu->async_handler.callback_data = motu;
0109
0110 err = fw_core_add_address_handler(&motu->async_handler,
0111 &resp_register_region);
0112 if (err < 0)
0113 return err;
0114
0115 err = snd_motu_transaction_reregister(motu);
0116 if (err < 0) {
0117 fw_core_remove_address_handler(&motu->async_handler);
0118 motu->async_handler.address_callback = NULL;
0119 }
0120
0121 return err;
0122 }
0123
0124 void snd_motu_transaction_unregister(struct snd_motu *motu)
0125 {
0126 __be32 data;
0127
0128 if (motu->async_handler.address_callback != NULL)
0129 fw_core_remove_address_handler(&motu->async_handler);
0130 motu->async_handler.address_callback = NULL;
0131
0132
0133 data = cpu_to_be32(0x00000000);
0134 snd_motu_transaction_write(motu, ASYNC_ADDR_HI, &data, sizeof(data));
0135 snd_motu_transaction_write(motu, ASYNC_ADDR_LO, &data, sizeof(data));
0136 }