2015-12-22 03:15:39 +03:00
/*
* oxfw - scs1x . c - a part of driver for OXFW970 / 971 based devices
*
* Copyright ( c ) Clemens Ladisch < clemens @ ladisch . de >
* Copyright ( c ) 2015 Takashi Sakamoto < o - takashi @ sakamocchi . jp >
*
* Licensed under the terms of the GNU General Public License , version 2.
*/
# include "oxfw.h"
2015-12-22 03:15:40 +03:00
# define HSS1394_ADDRESS 0xc007dedadadaULL
# define HSS1394_MAX_PACKET_SIZE 64
2015-12-22 03:15:41 +03:00
# define HSS1394_TAG_USER_DATA 0x00
2015-12-22 03:15:40 +03:00
# define HSS1394_TAG_CHANGE_ADDRESS 0xf1
struct fw_scs1x {
struct fw_address_handler hss_handler ;
2015-12-22 03:15:41 +03:00
u8 input_escape_count ;
struct snd_rawmidi_substream * input ;
2015-12-22 03:15:43 +03:00
/* For MIDI playback. */
struct snd_rawmidi_substream * output ;
bool output_idle ;
u8 output_status ;
u8 output_bytes ;
bool output_escaped ;
bool output_escape_high_nibble ;
2016-02-17 19:24:36 +03:00
struct work_struct work ;
2015-12-22 03:15:43 +03:00
wait_queue_head_t idle_wait ;
u8 buffer [ HSS1394_MAX_PACKET_SIZE ] ;
bool transaction_running ;
struct fw_transaction transaction ;
2016-02-24 03:26:32 +03:00
unsigned int transaction_bytes ;
2016-02-24 03:26:33 +03:00
bool error ;
2015-12-22 03:15:43 +03:00
struct fw_device * fw_dev ;
2015-12-22 03:15:40 +03:00
} ;
2015-12-22 03:15:41 +03:00
static const u8 sysex_escape_prefix [ ] = {
0xf0 , /* SysEx begin */
0x00 , 0x01 , 0x60 , /* Stanton DJ */
0x48 , 0x53 , 0x53 , /* "HSS" */
} ;
static void midi_input_escaped_byte ( struct snd_rawmidi_substream * stream ,
u8 byte )
{
u8 nibbles [ 2 ] ;
nibbles [ 0 ] = byte > > 4 ;
nibbles [ 1 ] = byte & 0x0f ;
snd_rawmidi_receive ( stream , nibbles , 2 ) ;
}
static void midi_input_byte ( struct fw_scs1x * scs ,
struct snd_rawmidi_substream * stream , u8 byte )
{
const u8 eox = 0xf7 ;
if ( scs - > input_escape_count > 0 ) {
midi_input_escaped_byte ( stream , byte ) ;
scs - > input_escape_count - - ;
if ( scs - > input_escape_count = = 0 )
snd_rawmidi_receive ( stream , & eox , sizeof ( eox ) ) ;
} else if ( byte = = 0xf9 ) {
snd_rawmidi_receive ( stream , sysex_escape_prefix ,
ARRAY_SIZE ( sysex_escape_prefix ) ) ;
midi_input_escaped_byte ( stream , 0x00 ) ;
midi_input_escaped_byte ( stream , 0xf9 ) ;
scs - > input_escape_count = 3 ;
} else {
snd_rawmidi_receive ( stream , & byte , 1 ) ;
}
}
static void midi_input_packet ( struct fw_scs1x * scs ,
struct snd_rawmidi_substream * stream ,
const u8 * data , unsigned int bytes )
{
unsigned int i ;
const u8 eox = 0xf7 ;
if ( data [ 0 ] = = HSS1394_TAG_USER_DATA ) {
for ( i = 1 ; i < bytes ; + + i )
midi_input_byte ( scs , stream , data [ i ] ) ;
} else {
snd_rawmidi_receive ( stream , sysex_escape_prefix ,
ARRAY_SIZE ( sysex_escape_prefix ) ) ;
for ( i = 0 ; i < bytes ; + + i )
midi_input_escaped_byte ( stream , data [ i ] ) ;
snd_rawmidi_receive ( stream , & eox , sizeof ( eox ) ) ;
}
}
2015-12-22 03:15:40 +03:00
static void handle_hss ( 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 )
{
2015-12-22 03:15:41 +03:00
struct fw_scs1x * scs = callback_data ;
struct snd_rawmidi_substream * stream ;
int rcode ;
if ( offset ! = scs - > hss_handler . offset ) {
rcode = RCODE_ADDRESS_ERROR ;
goto end ;
}
if ( tcode ! = TCODE_WRITE_QUADLET_REQUEST & &
tcode ! = TCODE_WRITE_BLOCK_REQUEST ) {
rcode = RCODE_TYPE_ERROR ;
goto end ;
}
if ( length > = 1 ) {
locking/atomics: COCCINELLE/treewide: Convert trivial ACCESS_ONCE() patterns to READ_ONCE()/WRITE_ONCE()
Please do not apply this to mainline directly, instead please re-run the
coccinelle script shown below and apply its output.
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't harmful, and changing them results in
churn.
However, for some features, the read/write distinction is critical to
correct operation. To distinguish these cases, separate read/write
accessors must be used. This patch migrates (most) remaining
ACCESS_ONCE() instances to {READ,WRITE}_ONCE(), using the following
coccinelle script:
----
// Convert trivial ACCESS_ONCE() uses to equivalent READ_ONCE() and
// WRITE_ONCE()
// $ make coccicheck COCCI=/home/mark/once.cocci SPFLAGS="--include-headers" MODE=patch
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: viro@zeniv.linux.org.uk
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-19-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-24 00:07:29 +03:00
stream = READ_ONCE ( scs - > input ) ;
2015-12-22 03:15:41 +03:00
if ( stream )
midi_input_packet ( scs , stream , data , length ) ;
}
rcode = RCODE_COMPLETE ;
end :
fw_send_response ( card , request , rcode ) ;
2015-12-22 03:15:40 +03:00
}
2015-12-22 03:15:43 +03:00
static void scs_write_callback ( struct fw_card * card , int rcode ,
void * data , size_t length , void * callback_data )
{
struct fw_scs1x * scs = callback_data ;
2016-02-24 03:26:33 +03:00
if ( ! rcode_is_permanent_error ( rcode ) ) {
/* Don't retry for this data. */
if ( rcode = = RCODE_COMPLETE )
scs - > transaction_bytes = 0 ;
} else {
scs - > error = true ;
}
2015-12-22 03:15:43 +03:00
scs - > transaction_running = false ;
2016-02-17 19:24:36 +03:00
schedule_work ( & scs - > work ) ;
2015-12-22 03:15:43 +03:00
}
static bool is_valid_running_status ( u8 status )
{
return status > = 0x80 & & status < = 0xef ;
}
static bool is_one_byte_cmd ( u8 status )
{
return status = = 0xf6 | |
status > = 0xf8 ;
}
static bool is_two_bytes_cmd ( u8 status )
{
return ( status > = 0xc0 & & status < = 0xdf ) | |
status = = 0xf1 | |
status = = 0xf3 ;
}
static bool is_three_bytes_cmd ( u8 status )
{
return ( status > = 0x80 & & status < = 0xbf ) | |
( status > = 0xe0 & & status < = 0xef ) | |
status = = 0xf2 ;
}
static bool is_invalid_cmd ( u8 status )
{
return status = = 0xf4 | |
status = = 0xf5 | |
status = = 0xf9 | |
status = = 0xfd ;
}
2016-02-17 19:24:36 +03:00
static void scs_output_work ( struct work_struct * work )
2015-12-22 03:15:43 +03:00
{
2016-02-17 19:24:36 +03:00
struct fw_scs1x * scs = container_of ( work , struct fw_scs1x , work ) ;
2015-12-22 03:15:43 +03:00
struct snd_rawmidi_substream * stream ;
unsigned int i ;
u8 byte ;
int generation ;
if ( scs - > transaction_running )
return ;
locking/atomics: COCCINELLE/treewide: Convert trivial ACCESS_ONCE() patterns to READ_ONCE()/WRITE_ONCE()
Please do not apply this to mainline directly, instead please re-run the
coccinelle script shown below and apply its output.
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't harmful, and changing them results in
churn.
However, for some features, the read/write distinction is critical to
correct operation. To distinguish these cases, separate read/write
accessors must be used. This patch migrates (most) remaining
ACCESS_ONCE() instances to {READ,WRITE}_ONCE(), using the following
coccinelle script:
----
// Convert trivial ACCESS_ONCE() uses to equivalent READ_ONCE() and
// WRITE_ONCE()
// $ make coccicheck COCCI=/home/mark/once.cocci SPFLAGS="--include-headers" MODE=patch
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: viro@zeniv.linux.org.uk
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-19-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-24 00:07:29 +03:00
stream = READ_ONCE ( scs - > output ) ;
2016-02-24 03:26:33 +03:00
if ( ! stream | | scs - > error ) {
2015-12-22 03:15:43 +03:00
scs - > output_idle = true ;
wake_up ( & scs - > idle_wait ) ;
return ;
}
2016-02-24 03:26:32 +03:00
if ( scs - > transaction_bytes > 0 )
goto retry ;
2015-12-22 03:15:43 +03:00
i = scs - > output_bytes ;
for ( ; ; ) {
if ( snd_rawmidi_transmit ( stream , & byte , 1 ) ! = 1 ) {
scs - > output_bytes = i ;
scs - > output_idle = true ;
wake_up ( & scs - > idle_wait ) ;
return ;
}
/*
* Convert from real MIDI to what I think the device expects ( no
* running status , one command per packet , unescaped SysExs ) .
*/
if ( scs - > output_escaped & & byte < 0x80 ) {
if ( scs - > output_escape_high_nibble ) {
if ( i < HSS1394_MAX_PACKET_SIZE ) {
scs - > buffer [ i ] = byte < < 4 ;
scs - > output_escape_high_nibble = false ;
}
} else {
scs - > buffer [ i + + ] | = byte & 0x0f ;
scs - > output_escape_high_nibble = true ;
}
} else if ( byte < 0x80 ) {
if ( i = = 1 ) {
if ( ! is_valid_running_status (
scs - > output_status ) )
continue ;
scs - > buffer [ 0 ] = HSS1394_TAG_USER_DATA ;
scs - > buffer [ i + + ] = scs - > output_status ;
}
scs - > buffer [ i + + ] = byte ;
if ( ( i = = 3 & & is_two_bytes_cmd ( scs - > output_status ) ) | |
( i = = 4 & & is_three_bytes_cmd ( scs - > output_status ) ) )
break ;
if ( i = = 1 + ARRAY_SIZE ( sysex_escape_prefix ) & &
! memcmp ( scs - > buffer + 1 , sysex_escape_prefix ,
ARRAY_SIZE ( sysex_escape_prefix ) ) ) {
scs - > output_escaped = true ;
scs - > output_escape_high_nibble = true ;
i = 0 ;
}
if ( i > = HSS1394_MAX_PACKET_SIZE )
i = 1 ;
} else if ( byte = = 0xf7 ) {
if ( scs - > output_escaped ) {
if ( i > = 1 & & scs - > output_escape_high_nibble & &
scs - > buffer [ 0 ] ! =
HSS1394_TAG_CHANGE_ADDRESS )
break ;
} else {
if ( i > 1 & & scs - > output_status = = 0xf0 ) {
scs - > buffer [ i + + ] = 0xf7 ;
break ;
}
}
i = 1 ;
scs - > output_escaped = false ;
} else if ( ! is_invalid_cmd ( byte ) & & byte < 0xf8 ) {
i = 1 ;
scs - > buffer [ 0 ] = HSS1394_TAG_USER_DATA ;
scs - > buffer [ i + + ] = byte ;
scs - > output_status = byte ;
scs - > output_escaped = false ;
if ( is_one_byte_cmd ( byte ) )
break ;
}
}
scs - > output_bytes = 1 ;
scs - > output_escaped = false ;
2016-02-24 03:26:32 +03:00
scs - > transaction_bytes = i ;
retry :
2015-12-22 03:15:43 +03:00
scs - > transaction_running = true ;
generation = scs - > fw_dev - > generation ;
smp_rmb ( ) ; /* node_id vs. generation */
fw_send_request ( scs - > fw_dev - > card , & scs - > transaction ,
TCODE_WRITE_BLOCK_REQUEST , scs - > fw_dev - > node_id ,
generation , scs - > fw_dev - > max_speed , HSS1394_ADDRESS ,
2016-02-24 03:26:32 +03:00
scs - > buffer , scs - > transaction_bytes ,
scs_write_callback , scs ) ;
2015-12-22 03:15:43 +03:00
}
2015-12-22 03:15:42 +03:00
static int midi_capture_open ( struct snd_rawmidi_substream * stream )
{
return 0 ;
}
static int midi_capture_close ( struct snd_rawmidi_substream * stream )
{
return 0 ;
}
static void midi_capture_trigger ( struct snd_rawmidi_substream * stream , int up )
{
struct fw_scs1x * scs = stream - > rmidi - > private_data ;
if ( up ) {
scs - > input_escape_count = 0 ;
locking/atomics: COCCINELLE/treewide: Convert trivial ACCESS_ONCE() patterns to READ_ONCE()/WRITE_ONCE()
Please do not apply this to mainline directly, instead please re-run the
coccinelle script shown below and apply its output.
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't harmful, and changing them results in
churn.
However, for some features, the read/write distinction is critical to
correct operation. To distinguish these cases, separate read/write
accessors must be used. This patch migrates (most) remaining
ACCESS_ONCE() instances to {READ,WRITE}_ONCE(), using the following
coccinelle script:
----
// Convert trivial ACCESS_ONCE() uses to equivalent READ_ONCE() and
// WRITE_ONCE()
// $ make coccicheck COCCI=/home/mark/once.cocci SPFLAGS="--include-headers" MODE=patch
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: viro@zeniv.linux.org.uk
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-19-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-24 00:07:29 +03:00
WRITE_ONCE ( scs - > input , stream ) ;
2015-12-22 03:15:42 +03:00
} else {
locking/atomics: COCCINELLE/treewide: Convert trivial ACCESS_ONCE() patterns to READ_ONCE()/WRITE_ONCE()
Please do not apply this to mainline directly, instead please re-run the
coccinelle script shown below and apply its output.
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't harmful, and changing them results in
churn.
However, for some features, the read/write distinction is critical to
correct operation. To distinguish these cases, separate read/write
accessors must be used. This patch migrates (most) remaining
ACCESS_ONCE() instances to {READ,WRITE}_ONCE(), using the following
coccinelle script:
----
// Convert trivial ACCESS_ONCE() uses to equivalent READ_ONCE() and
// WRITE_ONCE()
// $ make coccicheck COCCI=/home/mark/once.cocci SPFLAGS="--include-headers" MODE=patch
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: viro@zeniv.linux.org.uk
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-19-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-24 00:07:29 +03:00
WRITE_ONCE ( scs - > input , NULL ) ;
2015-12-22 03:15:42 +03:00
}
}
2015-12-22 03:15:44 +03:00
static int midi_playback_open ( struct snd_rawmidi_substream * stream )
{
return 0 ;
}
static int midi_playback_close ( struct snd_rawmidi_substream * stream )
{
return 0 ;
}
static void midi_playback_trigger ( struct snd_rawmidi_substream * stream , int up )
{
struct fw_scs1x * scs = stream - > rmidi - > private_data ;
if ( up ) {
scs - > output_status = 0 ;
scs - > output_bytes = 1 ;
scs - > output_escaped = false ;
scs - > output_idle = false ;
2016-02-24 03:26:32 +03:00
scs - > transaction_bytes = 0 ;
2016-02-24 03:26:33 +03:00
scs - > error = false ;
2015-12-22 03:15:44 +03:00
locking/atomics: COCCINELLE/treewide: Convert trivial ACCESS_ONCE() patterns to READ_ONCE()/WRITE_ONCE()
Please do not apply this to mainline directly, instead please re-run the
coccinelle script shown below and apply its output.
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't harmful, and changing them results in
churn.
However, for some features, the read/write distinction is critical to
correct operation. To distinguish these cases, separate read/write
accessors must be used. This patch migrates (most) remaining
ACCESS_ONCE() instances to {READ,WRITE}_ONCE(), using the following
coccinelle script:
----
// Convert trivial ACCESS_ONCE() uses to equivalent READ_ONCE() and
// WRITE_ONCE()
// $ make coccicheck COCCI=/home/mark/once.cocci SPFLAGS="--include-headers" MODE=patch
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: viro@zeniv.linux.org.uk
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-19-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-24 00:07:29 +03:00
WRITE_ONCE ( scs - > output , stream ) ;
2016-02-17 19:24:36 +03:00
schedule_work ( & scs - > work ) ;
2015-12-22 03:15:44 +03:00
} else {
locking/atomics: COCCINELLE/treewide: Convert trivial ACCESS_ONCE() patterns to READ_ONCE()/WRITE_ONCE()
Please do not apply this to mainline directly, instead please re-run the
coccinelle script shown below and apply its output.
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't harmful, and changing them results in
churn.
However, for some features, the read/write distinction is critical to
correct operation. To distinguish these cases, separate read/write
accessors must be used. This patch migrates (most) remaining
ACCESS_ONCE() instances to {READ,WRITE}_ONCE(), using the following
coccinelle script:
----
// Convert trivial ACCESS_ONCE() uses to equivalent READ_ONCE() and
// WRITE_ONCE()
// $ make coccicheck COCCI=/home/mark/once.cocci SPFLAGS="--include-headers" MODE=patch
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: viro@zeniv.linux.org.uk
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-19-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-24 00:07:29 +03:00
WRITE_ONCE ( scs - > output , NULL ) ;
2015-12-22 03:15:44 +03:00
}
}
static void midi_playback_drain ( struct snd_rawmidi_substream * stream )
{
struct fw_scs1x * scs = stream - > rmidi - > private_data ;
wait_event ( scs - > idle_wait , scs - > output_idle ) ;
}
2015-12-22 03:15:40 +03:00
static int register_address ( struct snd_oxfw * oxfw )
{
struct fw_scs1x * scs = oxfw - > spec ;
__be64 data ;
data = cpu_to_be64 ( ( ( u64 ) HSS1394_TAG_CHANGE_ADDRESS < < 56 ) |
scs - > hss_handler . offset ) ;
return snd_fw_transaction ( oxfw - > unit , TCODE_WRITE_BLOCK_REQUEST ,
HSS1394_ADDRESS , & data , sizeof ( data ) , 0 ) ;
}
static void remove_scs1x ( struct snd_rawmidi * rmidi )
{
struct fw_scs1x * scs = rmidi - > private_data ;
fw_core_remove_address_handler ( & scs - > hss_handler ) ;
}
void snd_oxfw_scs1x_update ( struct snd_oxfw * oxfw )
{
register_address ( oxfw ) ;
}
2015-12-22 03:15:39 +03:00
int snd_oxfw_scs1x_add ( struct snd_oxfw * oxfw )
{
2017-08-22 16:58:15 +03:00
static const struct snd_rawmidi_ops midi_capture_ops = {
. open = midi_capture_open ,
. close = midi_capture_close ,
. trigger = midi_capture_trigger ,
} ;
2017-01-13 14:30:22 +03:00
static const struct snd_rawmidi_ops midi_playback_ops = {
. open = midi_playback_open ,
. close = midi_playback_close ,
. trigger = midi_playback_trigger ,
. drain = midi_playback_drain ,
} ;
2015-12-22 03:15:39 +03:00
struct snd_rawmidi * rmidi ;
2015-12-22 03:15:40 +03:00
struct fw_scs1x * scs ;
2015-12-22 03:15:39 +03:00
int err ;
2018-10-03 02:21:53 +03:00
scs = devm_kzalloc ( & oxfw - > card - > card_dev , sizeof ( struct fw_scs1x ) ,
GFP_KERNEL ) ;
if ( ! scs )
2015-12-22 03:15:40 +03:00
return - ENOMEM ;
2015-12-22 03:15:43 +03:00
scs - > fw_dev = fw_parent_device ( oxfw - > unit ) ;
2015-12-22 03:15:40 +03:00
oxfw - > spec = scs ;
/* Allocate own handler for imcoming asynchronous transaction. */
scs - > hss_handler . length = HSS1394_MAX_PACKET_SIZE ;
scs - > hss_handler . address_callback = handle_hss ;
scs - > hss_handler . callback_data = scs ;
err = fw_core_add_address_handler ( & scs - > hss_handler ,
& fw_high_memory_region ) ;
if ( err < 0 )
return err ;
err = register_address ( oxfw ) ;
if ( err < 0 )
goto err_allocated ;
2015-12-22 03:15:39 +03:00
/* Use unique name for backward compatibility to scs1x module. */
2015-12-22 03:15:44 +03:00
err = snd_rawmidi_new ( oxfw - > card , " SCS.1x " , 0 , 1 , 1 , & rmidi ) ;
2015-12-22 03:15:39 +03:00
if ( err < 0 )
2015-12-22 03:15:40 +03:00
goto err_allocated ;
rmidi - > private_data = scs ;
rmidi - > private_free = remove_scs1x ;
2015-12-22 03:15:39 +03:00
snprintf ( rmidi - > name , sizeof ( rmidi - > name ) ,
" %s MIDI " , oxfw - > card - > shortname ) ;
2015-12-22 03:15:44 +03:00
rmidi - > info_flags = SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_DUPLEX ;
2015-12-22 03:15:42 +03:00
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_INPUT ,
& midi_capture_ops ) ;
2015-12-22 03:15:44 +03:00
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_OUTPUT ,
& midi_playback_ops ) ;
2015-12-22 03:15:42 +03:00
2016-02-17 19:24:36 +03:00
INIT_WORK ( & scs - > work , scs_output_work ) ;
2015-12-22 03:15:43 +03:00
init_waitqueue_head ( & scs - > idle_wait ) ;
scs - > output_idle = true ;
2015-12-22 03:15:40 +03:00
return 0 ;
err_allocated :
fw_core_remove_address_handler ( & scs - > hss_handler ) ;
2015-12-22 03:15:39 +03:00
return err ;
}