Merge branch 'for-linus-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[cascardo/linux.git] / sound / firewire / oxfw / oxfw-scs1x.c
1 /*
2  * oxfw-scs1x.c - a part of driver for OXFW970/971 based devices
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6  *
7  * Licensed under the terms of the GNU General Public License, version 2.
8  */
9
10 #include "oxfw.h"
11
12 #define HSS1394_ADDRESS                 0xc007dedadadaULL
13 #define HSS1394_MAX_PACKET_SIZE         64
14 #define HSS1394_TAG_USER_DATA           0x00
15 #define HSS1394_TAG_CHANGE_ADDRESS      0xf1
16
17 struct fw_scs1x {
18         struct fw_address_handler hss_handler;
19         u8 input_escape_count;
20         struct snd_rawmidi_substream *input;
21
22         /* For MIDI playback. */
23         struct snd_rawmidi_substream *output;
24         bool output_idle;
25         u8 output_status;
26         u8 output_bytes;
27         bool output_escaped;
28         bool output_escape_high_nibble;
29         struct work_struct work;
30         wait_queue_head_t idle_wait;
31         u8 buffer[HSS1394_MAX_PACKET_SIZE];
32         bool transaction_running;
33         struct fw_transaction transaction;
34         unsigned int transaction_bytes;
35         bool error;
36         struct fw_device *fw_dev;
37 };
38
39 static const u8 sysex_escape_prefix[] = {
40         0xf0,                   /* SysEx begin */
41         0x00, 0x01, 0x60,       /* Stanton DJ */
42         0x48, 0x53, 0x53,       /* "HSS" */
43 };
44
45 static void midi_input_escaped_byte(struct snd_rawmidi_substream *stream,
46                                     u8 byte)
47 {
48         u8 nibbles[2];
49
50         nibbles[0] = byte >> 4;
51         nibbles[1] = byte & 0x0f;
52         snd_rawmidi_receive(stream, nibbles, 2);
53 }
54
55 static void midi_input_byte(struct fw_scs1x *scs,
56                             struct snd_rawmidi_substream *stream, u8 byte)
57 {
58         const u8 eox = 0xf7;
59
60         if (scs->input_escape_count > 0) {
61                 midi_input_escaped_byte(stream, byte);
62                 scs->input_escape_count--;
63                 if (scs->input_escape_count == 0)
64                         snd_rawmidi_receive(stream, &eox, sizeof(eox));
65         } else if (byte == 0xf9) {
66                 snd_rawmidi_receive(stream, sysex_escape_prefix,
67                                     ARRAY_SIZE(sysex_escape_prefix));
68                 midi_input_escaped_byte(stream, 0x00);
69                 midi_input_escaped_byte(stream, 0xf9);
70                 scs->input_escape_count = 3;
71         } else {
72                 snd_rawmidi_receive(stream, &byte, 1);
73         }
74 }
75
76 static void midi_input_packet(struct fw_scs1x *scs,
77                               struct snd_rawmidi_substream *stream,
78                               const u8 *data, unsigned int bytes)
79 {
80         unsigned int i;
81         const u8 eox = 0xf7;
82
83         if (data[0] == HSS1394_TAG_USER_DATA) {
84                 for (i = 1; i < bytes; ++i)
85                         midi_input_byte(scs, stream, data[i]);
86         } else {
87                 snd_rawmidi_receive(stream, sysex_escape_prefix,
88                                     ARRAY_SIZE(sysex_escape_prefix));
89                 for (i = 0; i < bytes; ++i)
90                         midi_input_escaped_byte(stream, data[i]);
91                 snd_rawmidi_receive(stream, &eox, sizeof(eox));
92         }
93 }
94
95 static void handle_hss(struct fw_card *card, struct fw_request *request,
96                        int tcode, int destination, int source, int generation,
97                        unsigned long long offset, void *data, size_t length,
98                        void *callback_data)
99 {
100         struct fw_scs1x *scs = callback_data;
101         struct snd_rawmidi_substream *stream;
102         int rcode;
103
104         if (offset != scs->hss_handler.offset) {
105                 rcode = RCODE_ADDRESS_ERROR;
106                 goto end;
107         }
108         if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
109             tcode != TCODE_WRITE_BLOCK_REQUEST) {
110                 rcode = RCODE_TYPE_ERROR;
111                 goto end;
112         }
113
114         if (length >= 1) {
115                 stream = ACCESS_ONCE(scs->input);
116                 if (stream)
117                         midi_input_packet(scs, stream, data, length);
118         }
119
120         rcode = RCODE_COMPLETE;
121 end:
122         fw_send_response(card, request, rcode);
123 }
124
125 static void scs_write_callback(struct fw_card *card, int rcode,
126                                void *data, size_t length, void *callback_data)
127 {
128         struct fw_scs1x *scs = callback_data;
129
130         if (!rcode_is_permanent_error(rcode)) {
131                 /* Don't retry for this data. */
132                 if (rcode == RCODE_COMPLETE)
133                         scs->transaction_bytes = 0;
134         } else {
135                 scs->error = true;
136         }
137
138         scs->transaction_running = false;
139         schedule_work(&scs->work);
140 }
141
142 static bool is_valid_running_status(u8 status)
143 {
144         return status >= 0x80 && status <= 0xef;
145 }
146
147 static bool is_one_byte_cmd(u8 status)
148 {
149         return status == 0xf6 ||
150                status >= 0xf8;
151 }
152
153 static bool is_two_bytes_cmd(u8 status)
154 {
155         return (status >= 0xc0 && status <= 0xdf) ||
156                status == 0xf1 ||
157                status == 0xf3;
158 }
159
160 static bool is_three_bytes_cmd(u8 status)
161 {
162         return (status >= 0x80 && status <= 0xbf) ||
163                (status >= 0xe0 && status <= 0xef) ||
164                status == 0xf2;
165 }
166
167 static bool is_invalid_cmd(u8 status)
168 {
169         return status == 0xf4 ||
170                status == 0xf5 ||
171                status == 0xf9 ||
172                status == 0xfd;
173 }
174
175 static void scs_output_work(struct work_struct *work)
176 {
177         struct fw_scs1x *scs = container_of(work, struct fw_scs1x, work);
178         struct snd_rawmidi_substream *stream;
179         unsigned int i;
180         u8 byte;
181         int generation;
182
183         if (scs->transaction_running)
184                 return;
185
186         stream = ACCESS_ONCE(scs->output);
187         if (!stream || scs->error) {
188                 scs->output_idle = true;
189                 wake_up(&scs->idle_wait);
190                 return;
191         }
192
193         if (scs->transaction_bytes > 0)
194                 goto retry;
195
196         i = scs->output_bytes;
197         for (;;) {
198                 if (snd_rawmidi_transmit(stream, &byte, 1) != 1) {
199                         scs->output_bytes = i;
200                         scs->output_idle = true;
201                         wake_up(&scs->idle_wait);
202                         return;
203                 }
204                 /*
205                  * Convert from real MIDI to what I think the device expects (no
206                  * running status, one command per packet, unescaped SysExs).
207                  */
208                 if (scs->output_escaped && byte < 0x80) {
209                         if (scs->output_escape_high_nibble) {
210                                 if (i < HSS1394_MAX_PACKET_SIZE) {
211                                         scs->buffer[i] = byte << 4;
212                                         scs->output_escape_high_nibble = false;
213                                 }
214                         } else {
215                                 scs->buffer[i++] |= byte & 0x0f;
216                                 scs->output_escape_high_nibble = true;
217                         }
218                 } else if (byte < 0x80) {
219                         if (i == 1) {
220                                 if (!is_valid_running_status(
221                                                         scs->output_status))
222                                         continue;
223                                 scs->buffer[0] = HSS1394_TAG_USER_DATA;
224                                 scs->buffer[i++] = scs->output_status;
225                         }
226                         scs->buffer[i++] = byte;
227                         if ((i == 3 && is_two_bytes_cmd(scs->output_status)) ||
228                             (i == 4 && is_three_bytes_cmd(scs->output_status)))
229                                 break;
230                         if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) &&
231                             !memcmp(scs->buffer + 1, sysex_escape_prefix,
232                                     ARRAY_SIZE(sysex_escape_prefix))) {
233                                 scs->output_escaped = true;
234                                 scs->output_escape_high_nibble = true;
235                                 i = 0;
236                         }
237                         if (i >= HSS1394_MAX_PACKET_SIZE)
238                                 i = 1;
239                 } else if (byte == 0xf7) {
240                         if (scs->output_escaped) {
241                                 if (i >= 1 && scs->output_escape_high_nibble &&
242                                     scs->buffer[0] !=
243                                                 HSS1394_TAG_CHANGE_ADDRESS)
244                                         break;
245                         } else {
246                                 if (i > 1 && scs->output_status == 0xf0) {
247                                         scs->buffer[i++] = 0xf7;
248                                         break;
249                                 }
250                         }
251                         i = 1;
252                         scs->output_escaped = false;
253                 } else if (!is_invalid_cmd(byte) && byte < 0xf8) {
254                         i = 1;
255                         scs->buffer[0] = HSS1394_TAG_USER_DATA;
256                         scs->buffer[i++] = byte;
257                         scs->output_status = byte;
258                         scs->output_escaped = false;
259                         if (is_one_byte_cmd(byte))
260                                 break;
261                 }
262         }
263         scs->output_bytes = 1;
264         scs->output_escaped = false;
265
266         scs->transaction_bytes = i;
267 retry:
268         scs->transaction_running = true;
269         generation = scs->fw_dev->generation;
270         smp_rmb(); /* node_id vs. generation */
271         fw_send_request(scs->fw_dev->card, &scs->transaction,
272                         TCODE_WRITE_BLOCK_REQUEST, scs->fw_dev->node_id,
273                         generation, scs->fw_dev->max_speed, HSS1394_ADDRESS,
274                         scs->buffer, scs->transaction_bytes,
275                         scs_write_callback, scs);
276 }
277
278 static int midi_capture_open(struct snd_rawmidi_substream *stream)
279 {
280         return 0;
281 }
282
283 static int midi_capture_close(struct snd_rawmidi_substream *stream)
284 {
285         return 0;
286 }
287
288 static void midi_capture_trigger(struct snd_rawmidi_substream *stream, int up)
289 {
290         struct fw_scs1x *scs = stream->rmidi->private_data;
291
292         if (up) {
293                 scs->input_escape_count = 0;
294                 ACCESS_ONCE(scs->input) = stream;
295         } else {
296                 ACCESS_ONCE(scs->input) = NULL;
297         }
298 }
299
300 static struct snd_rawmidi_ops midi_capture_ops = {
301         .open    = midi_capture_open,
302         .close   = midi_capture_close,
303         .trigger = midi_capture_trigger,
304 };
305
306 static int midi_playback_open(struct snd_rawmidi_substream *stream)
307 {
308         return 0;
309 }
310
311 static int midi_playback_close(struct snd_rawmidi_substream *stream)
312 {
313         return 0;
314 }
315
316 static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up)
317 {
318         struct fw_scs1x *scs = stream->rmidi->private_data;
319
320         if (up) {
321                 scs->output_status = 0;
322                 scs->output_bytes = 1;
323                 scs->output_escaped = false;
324                 scs->output_idle = false;
325                 scs->transaction_bytes = 0;
326                 scs->error = false;
327
328                 ACCESS_ONCE(scs->output) = stream;
329                 schedule_work(&scs->work);
330         } else {
331                 ACCESS_ONCE(scs->output) = NULL;
332         }
333 }
334 static void midi_playback_drain(struct snd_rawmidi_substream *stream)
335 {
336         struct fw_scs1x *scs = stream->rmidi->private_data;
337
338         wait_event(scs->idle_wait, scs->output_idle);
339 }
340
341 static struct snd_rawmidi_ops midi_playback_ops = {
342         .open    = midi_playback_open,
343         .close   = midi_playback_close,
344         .trigger = midi_playback_trigger,
345         .drain   = midi_playback_drain,
346 };
347 static int register_address(struct snd_oxfw *oxfw)
348 {
349         struct fw_scs1x *scs = oxfw->spec;
350         __be64 data;
351
352         data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
353                             scs->hss_handler.offset);
354         return snd_fw_transaction(oxfw->unit, TCODE_WRITE_BLOCK_REQUEST,
355                                   HSS1394_ADDRESS, &data, sizeof(data), 0);
356 }
357
358 static void remove_scs1x(struct snd_rawmidi *rmidi)
359 {
360         struct fw_scs1x *scs = rmidi->private_data;
361
362         fw_core_remove_address_handler(&scs->hss_handler);
363 }
364
365 void snd_oxfw_scs1x_update(struct snd_oxfw *oxfw)
366 {
367         register_address(oxfw);
368 }
369
370 int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw)
371 {
372         struct snd_rawmidi *rmidi;
373         struct fw_scs1x *scs;
374         int err;
375
376         scs = kzalloc(sizeof(struct fw_scs1x), GFP_KERNEL);
377         if (scs == NULL)
378                 return -ENOMEM;
379         scs->fw_dev = fw_parent_device(oxfw->unit);
380         oxfw->spec = scs;
381
382         /* Allocate own handler for imcoming asynchronous transaction. */
383         scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE;
384         scs->hss_handler.address_callback = handle_hss;
385         scs->hss_handler.callback_data = scs;
386         err = fw_core_add_address_handler(&scs->hss_handler,
387                                           &fw_high_memory_region);
388         if (err < 0)
389                 return err;
390
391         err = register_address(oxfw);
392         if (err < 0)
393                 goto err_allocated;
394
395         /* Use unique name for backward compatibility to scs1x module. */
396         err = snd_rawmidi_new(oxfw->card, "SCS.1x", 0, 1, 1, &rmidi);
397         if (err < 0)
398                 goto err_allocated;
399         rmidi->private_data = scs;
400         rmidi->private_free = remove_scs1x;
401
402         snprintf(rmidi->name, sizeof(rmidi->name),
403                  "%s MIDI", oxfw->card->shortname);
404
405         rmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT |
406                             SNDRV_RAWMIDI_INFO_OUTPUT |
407                             SNDRV_RAWMIDI_INFO_DUPLEX;
408         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
409                             &midi_capture_ops);
410         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
411                             &midi_playback_ops);
412
413         INIT_WORK(&scs->work, scs_output_work);
414         init_waitqueue_head(&scs->idle_wait);
415         scs->output_idle = true;
416
417         return 0;
418 err_allocated:
419         fw_core_remove_address_handler(&scs->hss_handler);
420         return err;
421 }