1*44b73088STakashi Sakamoto /* 2*44b73088STakashi Sakamoto * digi00x-transaction.c - a part of driver for Digidesign Digi 002/003 family 3*44b73088STakashi Sakamoto * 4*44b73088STakashi Sakamoto * Copyright (c) 2014-2015 Takashi Sakamoto 5*44b73088STakashi Sakamoto * 6*44b73088STakashi Sakamoto * Licensed under the terms of the GNU General Public License, version 2. 7*44b73088STakashi Sakamoto */ 8*44b73088STakashi Sakamoto 9*44b73088STakashi Sakamoto #include <sound/asound.h> 10*44b73088STakashi Sakamoto #include "digi00x.h" 11*44b73088STakashi Sakamoto 12*44b73088STakashi Sakamoto static void handle_unknown_message(struct snd_dg00x *dg00x, 13*44b73088STakashi Sakamoto unsigned long long offset, __be32 *buf) 14*44b73088STakashi Sakamoto { 15*44b73088STakashi Sakamoto unsigned long flags; 16*44b73088STakashi Sakamoto 17*44b73088STakashi Sakamoto spin_lock_irqsave(&dg00x->lock, flags); 18*44b73088STakashi Sakamoto dg00x->msg = be32_to_cpu(*buf); 19*44b73088STakashi Sakamoto spin_unlock_irqrestore(&dg00x->lock, flags); 20*44b73088STakashi Sakamoto 21*44b73088STakashi Sakamoto wake_up(&dg00x->hwdep_wait); 22*44b73088STakashi Sakamoto } 23*44b73088STakashi Sakamoto 24*44b73088STakashi Sakamoto static void handle_message(struct fw_card *card, struct fw_request *request, 25*44b73088STakashi Sakamoto int tcode, int destination, int source, 26*44b73088STakashi Sakamoto int generation, unsigned long long offset, 27*44b73088STakashi Sakamoto void *data, size_t length, void *callback_data) 28*44b73088STakashi Sakamoto { 29*44b73088STakashi Sakamoto struct snd_dg00x *dg00x = callback_data; 30*44b73088STakashi Sakamoto __be32 *buf = (__be32 *)data; 31*44b73088STakashi Sakamoto 32*44b73088STakashi Sakamoto if (offset == dg00x->async_handler.offset) 33*44b73088STakashi Sakamoto handle_unknown_message(dg00x, offset, buf); 34*44b73088STakashi Sakamoto 35*44b73088STakashi Sakamoto fw_send_response(card, request, RCODE_COMPLETE); 36*44b73088STakashi Sakamoto } 37*44b73088STakashi Sakamoto 38*44b73088STakashi Sakamoto int snd_dg00x_transaction_reregister(struct snd_dg00x *dg00x) 39*44b73088STakashi Sakamoto { 40*44b73088STakashi Sakamoto struct fw_device *device = fw_parent_device(dg00x->unit); 41*44b73088STakashi Sakamoto __be32 data[2]; 42*44b73088STakashi Sakamoto 43*44b73088STakashi Sakamoto /* Unknown. 4bytes. */ 44*44b73088STakashi Sakamoto data[0] = cpu_to_be32((device->card->node_id << 16) | 45*44b73088STakashi Sakamoto (dg00x->async_handler.offset >> 32)); 46*44b73088STakashi Sakamoto data[1] = cpu_to_be32(dg00x->async_handler.offset); 47*44b73088STakashi Sakamoto return snd_fw_transaction(dg00x->unit, TCODE_WRITE_BLOCK_REQUEST, 48*44b73088STakashi Sakamoto DG00X_ADDR_BASE + DG00X_OFFSET_MESSAGE_ADDR, 49*44b73088STakashi Sakamoto &data, sizeof(data), 0); 50*44b73088STakashi Sakamoto } 51*44b73088STakashi Sakamoto 52*44b73088STakashi Sakamoto int snd_dg00x_transaction_register(struct snd_dg00x *dg00x) 53*44b73088STakashi Sakamoto { 54*44b73088STakashi Sakamoto static const struct fw_address_region resp_register_region = { 55*44b73088STakashi Sakamoto .start = 0xffffe0000000ull, 56*44b73088STakashi Sakamoto .end = 0xffffe000ffffull, 57*44b73088STakashi Sakamoto }; 58*44b73088STakashi Sakamoto int err; 59*44b73088STakashi Sakamoto 60*44b73088STakashi Sakamoto dg00x->async_handler.length = 4; 61*44b73088STakashi Sakamoto dg00x->async_handler.address_callback = handle_message; 62*44b73088STakashi Sakamoto dg00x->async_handler.callback_data = dg00x; 63*44b73088STakashi Sakamoto 64*44b73088STakashi Sakamoto err = fw_core_add_address_handler(&dg00x->async_handler, 65*44b73088STakashi Sakamoto &resp_register_region); 66*44b73088STakashi Sakamoto if (err < 0) 67*44b73088STakashi Sakamoto return err; 68*44b73088STakashi Sakamoto 69*44b73088STakashi Sakamoto err = snd_dg00x_transaction_reregister(dg00x); 70*44b73088STakashi Sakamoto if (err < 0) { 71*44b73088STakashi Sakamoto fw_core_remove_address_handler(&dg00x->async_handler); 72*44b73088STakashi Sakamoto dg00x->async_handler.address_callback = NULL; 73*44b73088STakashi Sakamoto } 74*44b73088STakashi Sakamoto 75*44b73088STakashi Sakamoto return err; 76*44b73088STakashi Sakamoto } 77*44b73088STakashi Sakamoto 78*44b73088STakashi Sakamoto void snd_dg00x_transaction_unregister(struct snd_dg00x *dg00x) 79*44b73088STakashi Sakamoto { 80*44b73088STakashi Sakamoto fw_core_remove_address_handler(&dg00x->async_handler); 81*44b73088STakashi Sakamoto } 82