2019-05-29 16:57:59 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2015-09-30 09:39:22 +09:00
/*
* digi00x - transaction . c - a part of driver for Digidesign Digi 002 / 003 family
*
* Copyright ( c ) 2014 - 2015 Takashi Sakamoto
*/
# include <sound/asound.h>
# include "digi00x.h"
static void handle_unknown_message ( struct snd_dg00x * dg00x ,
unsigned long long offset , __be32 * buf )
{
unsigned long flags ;
spin_lock_irqsave ( & dg00x - > lock , flags ) ;
dg00x - > msg = be32_to_cpu ( * buf ) ;
spin_unlock_irqrestore ( & dg00x - > lock , flags ) ;
wake_up ( & dg00x - > hwdep_wait ) ;
}
static void handle_message ( struct fw_card * card , struct fw_request * request ,
int tcode , int destination , int source ,
int generation , unsigned long long offset ,
void * data , size_t length , void * callback_data )
{
struct snd_dg00x * dg00x = callback_data ;
__be32 * buf = ( __be32 * ) data ;
2017-04-02 23:48:27 +09:00
fw_send_response ( card , request , RCODE_COMPLETE ) ;
2015-09-30 09:39:22 +09:00
if ( offset = = dg00x - > async_handler . offset )
handle_unknown_message ( dg00x , offset , buf ) ;
}
int snd_dg00x_transaction_reregister ( struct snd_dg00x * dg00x )
{
struct fw_device * device = fw_parent_device ( dg00x - > unit ) ;
__be32 data [ 2 ] ;
/* Unknown. 4bytes. */
data [ 0 ] = cpu_to_be32 ( ( device - > card - > node_id < < 16 ) |
( dg00x - > async_handler . offset > > 32 ) ) ;
data [ 1 ] = cpu_to_be32 ( dg00x - > async_handler . offset ) ;
return snd_fw_transaction ( dg00x - > unit , TCODE_WRITE_BLOCK_REQUEST ,
2017-04-02 23:48:27 +09:00
DG00X_ADDR_BASE + DG00X_OFFSET_MESSAGE_ADDR ,
2015-10-11 12:30:17 +09:00
& data , sizeof ( data ) , 0 ) ;
2015-09-30 09:39:22 +09:00
}
2017-04-02 23:48:27 +09:00
void snd_dg00x_transaction_unregister ( struct snd_dg00x * dg00x )
{
if ( dg00x - > async_handler . callback_data = = NULL )
return ;
fw_core_remove_address_handler ( & dg00x - > async_handler ) ;
dg00x - > async_handler . callback_data = NULL ;
}
2015-09-30 09:39:22 +09:00
int snd_dg00x_transaction_register ( struct snd_dg00x * dg00x )
{
static const struct fw_address_region resp_register_region = {
. start = 0xffffe0000000ull ,
. end = 0xffffe000ffffull ,
} ;
int err ;
2017-04-02 23:48:27 +09:00
dg00x - > async_handler . length = 4 ;
2015-09-30 09:39:22 +09:00
dg00x - > async_handler . address_callback = handle_message ;
dg00x - > async_handler . callback_data = dg00x ;
err = fw_core_add_address_handler ( & dg00x - > async_handler ,
& resp_register_region ) ;
if ( err < 0 )
return err ;
err = snd_dg00x_transaction_reregister ( dg00x ) ;
2015-10-11 12:30:18 +09:00
if ( err < 0 )
2017-04-02 23:48:27 +09:00
snd_dg00x_transaction_unregister ( dg00x ) ;
2015-09-30 09:39:22 +09:00
return err ;
}