144b73088STakashi Sakamoto /* 244b73088STakashi Sakamoto * digi00x-transaction.c - a part of driver for Digidesign Digi 002/003 family 344b73088STakashi Sakamoto * 444b73088STakashi Sakamoto * Copyright (c) 2014-2015 Takashi Sakamoto 544b73088STakashi Sakamoto * 644b73088STakashi Sakamoto * Licensed under the terms of the GNU General Public License, version 2. 744b73088STakashi Sakamoto */ 844b73088STakashi Sakamoto 944b73088STakashi Sakamoto #include <sound/asound.h> 1044b73088STakashi Sakamoto #include "digi00x.h" 1144b73088STakashi Sakamoto 1244b73088STakashi Sakamoto static void handle_unknown_message(struct snd_dg00x *dg00x, 1344b73088STakashi Sakamoto unsigned long long offset, __be32 *buf) 1444b73088STakashi Sakamoto { 1544b73088STakashi Sakamoto unsigned long flags; 1644b73088STakashi Sakamoto 1744b73088STakashi Sakamoto spin_lock_irqsave(&dg00x->lock, flags); 1844b73088STakashi Sakamoto dg00x->msg = be32_to_cpu(*buf); 1944b73088STakashi Sakamoto spin_unlock_irqrestore(&dg00x->lock, flags); 2044b73088STakashi Sakamoto 2144b73088STakashi Sakamoto wake_up(&dg00x->hwdep_wait); 2244b73088STakashi Sakamoto } 2344b73088STakashi Sakamoto 2444b73088STakashi Sakamoto static void handle_message(struct fw_card *card, struct fw_request *request, 2544b73088STakashi Sakamoto int tcode, int destination, int source, 2644b73088STakashi Sakamoto int generation, unsigned long long offset, 2744b73088STakashi Sakamoto void *data, size_t length, void *callback_data) 2844b73088STakashi Sakamoto { 2944b73088STakashi Sakamoto struct snd_dg00x *dg00x = callback_data; 3044b73088STakashi Sakamoto __be32 *buf = (__be32 *)data; 3144b73088STakashi Sakamoto 32*fdb2b2eeSTakashi Sakamoto fw_send_response(card, request, RCODE_COMPLETE); 33*fdb2b2eeSTakashi Sakamoto 3444b73088STakashi Sakamoto if (offset == dg00x->async_handler.offset) 3544b73088STakashi Sakamoto handle_unknown_message(dg00x, offset, buf); 3644b73088STakashi Sakamoto } 3744b73088STakashi Sakamoto 3844b73088STakashi Sakamoto int snd_dg00x_transaction_reregister(struct snd_dg00x *dg00x) 3944b73088STakashi Sakamoto { 4044b73088STakashi Sakamoto struct fw_device *device = fw_parent_device(dg00x->unit); 4144b73088STakashi Sakamoto __be32 data[2]; 4244b73088STakashi Sakamoto 4344b73088STakashi Sakamoto /* Unknown. 4bytes. */ 4444b73088STakashi Sakamoto data[0] = cpu_to_be32((device->card->node_id << 16) | 4544b73088STakashi Sakamoto (dg00x->async_handler.offset >> 32)); 4644b73088STakashi Sakamoto data[1] = cpu_to_be32(dg00x->async_handler.offset); 47*fdb2b2eeSTakashi Sakamoto return snd_fw_transaction(dg00x->unit, TCODE_WRITE_BLOCK_REQUEST, 4844b73088STakashi Sakamoto DG00X_ADDR_BASE + DG00X_OFFSET_MESSAGE_ADDR, 4944b73088STakashi Sakamoto &data, sizeof(data), 0); 50*fdb2b2eeSTakashi Sakamoto } 513646a54aSTakashi Sakamoto 52*fdb2b2eeSTakashi Sakamoto void snd_dg00x_transaction_unregister(struct snd_dg00x *dg00x) 53*fdb2b2eeSTakashi Sakamoto { 54*fdb2b2eeSTakashi Sakamoto if (dg00x->async_handler.callback_data == NULL) 55*fdb2b2eeSTakashi Sakamoto return; 56*fdb2b2eeSTakashi Sakamoto 57*fdb2b2eeSTakashi Sakamoto fw_core_remove_address_handler(&dg00x->async_handler); 58*fdb2b2eeSTakashi Sakamoto 59*fdb2b2eeSTakashi Sakamoto dg00x->async_handler.callback_data = NULL; 6044b73088STakashi Sakamoto } 6144b73088STakashi Sakamoto 6244b73088STakashi Sakamoto int snd_dg00x_transaction_register(struct snd_dg00x *dg00x) 6344b73088STakashi Sakamoto { 6444b73088STakashi Sakamoto static const struct fw_address_region resp_register_region = { 6544b73088STakashi Sakamoto .start = 0xffffe0000000ull, 6644b73088STakashi Sakamoto .end = 0xffffe000ffffull, 6744b73088STakashi Sakamoto }; 6844b73088STakashi Sakamoto int err; 6944b73088STakashi Sakamoto 70*fdb2b2eeSTakashi Sakamoto dg00x->async_handler.length = 4; 7144b73088STakashi Sakamoto dg00x->async_handler.address_callback = handle_message; 7244b73088STakashi Sakamoto dg00x->async_handler.callback_data = dg00x; 7344b73088STakashi Sakamoto 7444b73088STakashi Sakamoto err = fw_core_add_address_handler(&dg00x->async_handler, 7544b73088STakashi Sakamoto &resp_register_region); 7644b73088STakashi Sakamoto if (err < 0) 7744b73088STakashi Sakamoto return err; 7844b73088STakashi Sakamoto 7944b73088STakashi Sakamoto err = snd_dg00x_transaction_reregister(dg00x); 80b47f525fSTakashi Sakamoto if (err < 0) 81*fdb2b2eeSTakashi Sakamoto snd_dg00x_transaction_unregister(dg00x); 82b47f525fSTakashi Sakamoto 83b47f525fSTakashi Sakamoto return err; 8444b73088STakashi Sakamoto } 85