2 * oxfw-scs1x.c - a part of driver for OXFW970/971 based devices
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp>
7 * Licensed under the terms of the GNU General Public License, version 2.
12 #define HSS1394_ADDRESS 0xc007dedadadaULL
13 #define HSS1394_MAX_PACKET_SIZE 64
14 #define HSS1394_TAG_CHANGE_ADDRESS 0xf1
17 struct fw_address_handler hss_handler
;
20 static void handle_hss(struct fw_card
*card
, struct fw_request
*request
,
21 int tcode
, int destination
, int source
, int generation
,
22 unsigned long long offset
, void *data
, size_t length
,
25 fw_send_response(card
, request
, RCODE_COMPLETE
);
28 static int register_address(struct snd_oxfw
*oxfw
)
30 struct fw_scs1x
*scs
= oxfw
->spec
;
33 data
= cpu_to_be64(((u64
)HSS1394_TAG_CHANGE_ADDRESS
<< 56) |
34 scs
->hss_handler
.offset
);
35 return snd_fw_transaction(oxfw
->unit
, TCODE_WRITE_BLOCK_REQUEST
,
36 HSS1394_ADDRESS
, &data
, sizeof(data
), 0);
39 static void remove_scs1x(struct snd_rawmidi
*rmidi
)
41 struct fw_scs1x
*scs
= rmidi
->private_data
;
43 fw_core_remove_address_handler(&scs
->hss_handler
);
46 void snd_oxfw_scs1x_update(struct snd_oxfw
*oxfw
)
48 register_address(oxfw
);
51 int snd_oxfw_scs1x_add(struct snd_oxfw
*oxfw
)
53 struct snd_rawmidi
*rmidi
;
57 scs
= kzalloc(sizeof(struct fw_scs1x
), GFP_KERNEL
);
62 /* Allocate own handler for imcoming asynchronous transaction. */
63 scs
->hss_handler
.length
= HSS1394_MAX_PACKET_SIZE
;
64 scs
->hss_handler
.address_callback
= handle_hss
;
65 scs
->hss_handler
.callback_data
= scs
;
66 err
= fw_core_add_address_handler(&scs
->hss_handler
,
67 &fw_high_memory_region
);
71 err
= register_address(oxfw
);
75 /* Use unique name for backward compatibility to scs1x module. */
76 err
= snd_rawmidi_new(oxfw
->card
, "SCS.1x", 0, 0, 0, &rmidi
);
79 rmidi
->private_data
= scs
;
80 rmidi
->private_free
= remove_scs1x
;
82 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
83 "%s MIDI", oxfw
->card
->shortname
);
87 fw_core_remove_address_handler(&scs
->hss_handler
);