~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/firewire/fireface/ff-protocol-former.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 // ff-protocol-former.c - a part of driver for RME Fireface series
  3 //
  4 // Copyright (c) 2019 Takashi Sakamoto
  5 
  6 #include <linux/delay.h>
  7 
  8 #include "ff.h"
  9 
 10 #define FORMER_REG_SYNC_STATUS          0x0000801c0000ull
 11 /* For block write request. */
 12 #define FORMER_REG_FETCH_PCM_FRAMES     0x0000801c0000ull
 13 #define FORMER_REG_CLOCK_CONFIG         0x0000801c0004ull
 14 
 15 static int parse_clock_bits(u32 data, unsigned int *rate,
 16                             enum snd_ff_clock_src *src)
 17 {
 18         static const struct {
 19                 unsigned int rate;
 20                 u32 mask;
 21         } *rate_entry, rate_entries[] = {
 22                 {  32000, 0x00000002, },
 23                 {  44100, 0x00000000, },
 24                 {  48000, 0x00000006, },
 25                 {  64000, 0x0000000a, },
 26                 {  88200, 0x00000008, },
 27                 {  96000, 0x0000000e, },
 28                 { 128000, 0x00000012, },
 29                 { 176400, 0x00000010, },
 30                 { 192000, 0x00000016, },
 31         };
 32         static const struct {
 33                 enum snd_ff_clock_src src;
 34                 u32 mask;
 35         } *clk_entry, clk_entries[] = {
 36                 { SND_FF_CLOCK_SRC_ADAT1,       0x00000000, },
 37                 { SND_FF_CLOCK_SRC_ADAT2,       0x00000400, },
 38                 { SND_FF_CLOCK_SRC_SPDIF,       0x00000c00, },
 39                 { SND_FF_CLOCK_SRC_WORD,        0x00001000, },
 40                 { SND_FF_CLOCK_SRC_LTC,         0x00001800, },
 41         };
 42         int i;
 43 
 44         for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
 45                 rate_entry = rate_entries + i;
 46                 if ((data & 0x0000001e) == rate_entry->mask) {
 47                         *rate = rate_entry->rate;
 48                         break;
 49                 }
 50         }
 51         if (i == ARRAY_SIZE(rate_entries))
 52                 return -EIO;
 53 
 54         if (data & 0x00000001) {
 55                 *src = SND_FF_CLOCK_SRC_INTERNAL;
 56         } else {
 57                 for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
 58                         clk_entry = clk_entries + i;
 59                         if ((data & 0x00001c00) == clk_entry->mask) {
 60                                 *src = clk_entry->src;
 61                                 break;
 62                         }
 63                 }
 64                 if (i == ARRAY_SIZE(clk_entries))
 65                         return -EIO;
 66         }
 67 
 68         return 0;
 69 }
 70 
 71 static int former_get_clock(struct snd_ff *ff, unsigned int *rate,
 72                             enum snd_ff_clock_src *src)
 73 {
 74         __le32 reg;
 75         u32 data;
 76         int err;
 77 
 78         err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
 79                                  FORMER_REG_CLOCK_CONFIG, &reg, sizeof(reg), 0);
 80         if (err < 0)
 81                 return err;
 82         data = le32_to_cpu(reg);
 83 
 84         return parse_clock_bits(data, rate, src);
 85 }
 86 
 87 static int former_switch_fetching_mode(struct snd_ff *ff, bool enable)
 88 {
 89         unsigned int count;
 90         __le32 *reg;
 91         int i;
 92         int err;
 93 
 94         count = 0;
 95         for (i = 0; i < SND_FF_STREAM_MODE_COUNT; ++i)
 96                 count = max(count, ff->spec->pcm_playback_channels[i]);
 97 
 98         reg = kcalloc(count, sizeof(__le32), GFP_KERNEL);
 99         if (!reg)
100                 return -ENOMEM;
101 
102         if (!enable) {
103                 /*
104                  * Each quadlet is corresponding to data channels in a data
105                  * blocks in reverse order. Precisely, quadlets for available
106                  * data channels should be enabled. Here, I take second best
107                  * to fetch PCM frames from all of data channels regardless of
108                  * stf.
109                  */
110                 for (i = 0; i < count; ++i)
111                         reg[i] = cpu_to_le32(0x00000001);
112         }
113 
114         err = snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST,
115                                  FORMER_REG_FETCH_PCM_FRAMES, reg,
116                                  sizeof(__le32) * count, 0);
117         kfree(reg);
118         return err;
119 }
120 
121 static void dump_clock_config(struct snd_ff *ff, struct snd_info_buffer *buffer)
122 {
123         __le32 reg;
124         u32 data;
125         unsigned int rate;
126         enum snd_ff_clock_src src;
127         const char *label;
128         int err;
129 
130         err = snd_fw_transaction(ff->unit, TCODE_READ_BLOCK_REQUEST,
131                                  FORMER_REG_CLOCK_CONFIG, &reg, sizeof(reg), 0);
132         if (err < 0)
133                 return;
134         data = le32_to_cpu(reg);
135 
136         snd_iprintf(buffer, "Output S/PDIF format: %s (Emphasis: %s)\n",
137                     (data & 0x00000020) ? "Professional" : "Consumer",
138                     (data & 0x00000040) ? "on" : "off");
139 
140         snd_iprintf(buffer, "Optical output interface format: %s\n",
141                     (data & 0x00000100) ? "S/PDIF" : "ADAT");
142 
143         snd_iprintf(buffer, "Word output single speed: %s\n",
144                     (data & 0x00002000) ? "on" : "off");
145 
146         snd_iprintf(buffer, "S/PDIF input interface: %s\n",
147                     (data & 0x00000200) ? "Optical" : "Coaxial");
148 
149         err = parse_clock_bits(data, &rate, &src);
150         if (err < 0)
151                 return;
152         label = snd_ff_proc_get_clk_label(src);
153         if (!label)
154                 return;
155 
156         snd_iprintf(buffer, "Clock configuration: %d %s\n", rate, label);
157 }
158 
159 static void dump_sync_status(struct snd_ff *ff, struct snd_info_buffer *buffer)
160 {
161         static const struct {
162                 char *const label;
163                 u32 locked_mask;
164                 u32 synced_mask;
165         } *clk_entry, clk_entries[] = {
166                 { "WDClk",      0x40000000, 0x20000000, },
167                 { "S/PDIF",     0x00080000, 0x00040000, },
168                 { "ADAT1",      0x00000400, 0x00001000, },
169                 { "ADAT2",      0x00000800, 0x00002000, },
170         };
171         static const struct {
172                 char *const label;
173                 u32 mask;
174         } *referred_entry, referred_entries[] = {
175                 { "ADAT1",      0x00000000, },
176                 { "ADAT2",      0x00400000, },
177                 { "S/PDIF",     0x00c00000, },
178                 { "WDclk",      0x01000000, },
179                 { "TCO",        0x01400000, },
180         };
181         static const struct {
182                 unsigned int rate;
183                 u32 mask;
184         } *rate_entry, rate_entries[] = {
185                 { 32000,        0x02000000, },
186                 { 44100,        0x04000000, },
187                 { 48000,        0x06000000, },
188                 { 64000,        0x08000000, },
189                 { 88200,        0x0a000000, },
190                 { 96000,        0x0c000000, },
191                 { 128000,       0x0e000000, },
192                 { 176400,       0x10000000, },
193                 { 192000,       0x12000000, },
194         };
195         __le32 reg[2];
196         u32 data[2];
197         int i;
198         int err;
199 
200         err = snd_fw_transaction(ff->unit, TCODE_READ_BLOCK_REQUEST,
201                                  FORMER_REG_SYNC_STATUS, reg, sizeof(reg), 0);
202         if (err < 0)
203                 return;
204         data[0] = le32_to_cpu(reg[0]);
205         data[1] = le32_to_cpu(reg[1]);
206 
207         snd_iprintf(buffer, "External source detection:\n");
208 
209         for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
210                 const char *state;
211 
212                 clk_entry = clk_entries + i;
213                 if (data[0] & clk_entry->locked_mask) {
214                         if (data[0] & clk_entry->synced_mask)
215                                 state = "sync";
216                         else
217                                 state = "lock";
218                 } else {
219                         state = "none";
220                 }
221 
222                 snd_iprintf(buffer, "%s: %s\n", clk_entry->label, state);
223         }
224 
225         snd_iprintf(buffer, "Referred clock:\n");
226 
227         if (data[1] & 0x00000001) {
228                 snd_iprintf(buffer, "Internal\n");
229         } else {
230                 unsigned int rate;
231                 const char *label;
232 
233                 for (i = 0; i < ARRAY_SIZE(referred_entries); ++i) {
234                         referred_entry = referred_entries + i;
235                         if ((data[0] & 0x1e0000) == referred_entry->mask) {
236                                 label = referred_entry->label;
237                                 break;
238                         }
239                 }
240                 if (i == ARRAY_SIZE(referred_entries))
241                         label = "none";
242 
243                 for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
244                         rate_entry = rate_entries + i;
245                         if ((data[0] & 0x1e000000) == rate_entry->mask) {
246                                 rate = rate_entry->rate;
247                                 break;
248                         }
249                 }
250                 if (i == ARRAY_SIZE(rate_entries))
251                         rate = 0;
252 
253                 snd_iprintf(buffer, "%s %d\n", label, rate);
254         }
255 }
256 
257 static void former_dump_status(struct snd_ff *ff,
258                                struct snd_info_buffer *buffer)
259 {
260         dump_clock_config(ff, buffer);
261         dump_sync_status(ff, buffer);
262 }
263 
264 static int former_fill_midi_msg(struct snd_ff *ff,
265                                 struct snd_rawmidi_substream *substream,
266                                 unsigned int port)
267 {
268         u8 *buf = (u8 *)ff->msg_buf[port];
269         int len;
270         int i;
271 
272         len = snd_rawmidi_transmit_peek(substream, buf,
273                                         SND_FF_MAXIMIM_MIDI_QUADS);
274         if (len <= 0)
275                 return len;
276 
277         // One quadlet includes one byte.
278         for (i = len - 1; i >= 0; --i)
279                 ff->msg_buf[port][i] = cpu_to_le32(buf[i]);
280         ff->rx_bytes[port] = len;
281 
282         return len;
283 }
284 
285 #define FF800_STF               0x0000fc88f000
286 #define FF800_RX_PACKET_FORMAT  0x0000fc88f004
287 #define FF800_ALLOC_TX_STREAM   0x0000fc88f008
288 #define FF800_ISOC_COMM_START   0x0000fc88f00c
289 #define   FF800_TX_S800_FLAG    0x00000800
290 #define FF800_ISOC_COMM_STOP    0x0000fc88f010
291 
292 #define FF800_TX_PACKET_ISOC_CH 0x0000801c0008
293 
294 static int allocate_tx_resources(struct snd_ff *ff)
295 {
296         __le32 reg;
297         unsigned int count;
298         unsigned int tx_isoc_channel;
299         int err;
300 
301         reg = cpu_to_le32(ff->tx_stream.data_block_quadlets);
302         err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
303                                  FF800_ALLOC_TX_STREAM, &reg, sizeof(reg), 0);
304         if (err < 0)
305                 return err;
306 
307         // Wait till the format of tx packet is available.
308         count = 0;
309         while (count++ < 10) {
310                 u32 data;
311                 err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,
312                                 FF800_TX_PACKET_ISOC_CH, &reg, sizeof(reg), 0);
313                 if (err < 0)
314                         return err;
315 
316                 data = le32_to_cpu(reg);
317                 if (data != 0xffffffff) {
318                         tx_isoc_channel = data;
319                         break;
320                 }
321 
322                 msleep(50);
323         }
324         if (count >= 10)
325                 return -ETIMEDOUT;
326 
327         // NOTE: this is a makeshift to start OHCI 1394 IR context in the
328         // channel. On the other hand, 'struct fw_iso_resources.allocated' is
329         // not true and it's not deallocated at stop.
330         ff->tx_resources.channel = tx_isoc_channel;
331 
332         return 0;
333 }
334 
335 static int ff800_allocate_resources(struct snd_ff *ff, unsigned int rate)
336 {
337         u32 data;
338         __le32 reg;
339         int err;
340 
341         reg = cpu_to_le32(rate);
342         err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
343                                  FF800_STF, &reg, sizeof(reg), 0);
344         if (err < 0)
345                 return err;
346 
347         // If starting isochronous communication immediately, change of STF has
348         // no effect. In this case, the communication runs based on former STF.
349         // Let's sleep for a bit.
350         msleep(100);
351 
352         // Controllers should allocate isochronous resources for rx stream.
353         err = fw_iso_resources_allocate(&ff->rx_resources,
354                                 amdtp_stream_get_max_payload(&ff->rx_stream),
355                                 fw_parent_device(ff->unit)->max_speed);
356         if (err < 0)
357                 return err;
358 
359         // Set isochronous channel and the number of quadlets of rx packets.
360         // This should be done before the allocation of tx resources to avoid
361         // periodical noise.
362         data = ff->rx_stream.data_block_quadlets << 3;
363         data = (data << 8) | ff->rx_resources.channel;
364         reg = cpu_to_le32(data);
365         err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
366                                  FF800_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);
367         if (err < 0)
368                 return err;
369 
370         return allocate_tx_resources(ff);
371 }
372 
373 static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
374 {
375         unsigned int generation = ff->rx_resources.generation;
376         __le32 reg;
377 
378         if (generation != fw_parent_device(ff->unit)->card->generation) {
379                 int err = fw_iso_resources_update(&ff->rx_resources);
380                 if (err < 0)
381                         return err;
382         }
383 
384         reg = cpu_to_le32(0x80000000);
385         reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets);
386         if (fw_parent_device(ff->unit)->max_speed == SCODE_800)
387                 reg |= cpu_to_le32(FF800_TX_S800_FLAG);
388         return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
389                                  FF800_ISOC_COMM_START, &reg, sizeof(reg), 0);
390 }
391 
392 static void ff800_finish_session(struct snd_ff *ff)
393 {
394         __le32 reg;
395 
396         reg = cpu_to_le32(0x80000000);
397         snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
398                            FF800_ISOC_COMM_STOP, &reg, sizeof(reg), 0);
399 }
400 
401 // Fireface 800 doesn't allow drivers to register lower 4 bytes of destination
402 // address.
403 // A write transaction to clear registered higher 4 bytes of destination address
404 // has an effect to suppress asynchronous transaction from device.
405 static void ff800_handle_midi_msg(struct snd_ff *ff, unsigned int offset, const __le32 *buf,
406                                   size_t length, u32 tstamp)
407 {
408         int i;
409 
410         for (i = 0; i < length / 4; i++) {
411                 u8 byte = le32_to_cpu(buf[i]) & 0xff;
412                 struct snd_rawmidi_substream *substream;
413 
414                 substream = READ_ONCE(ff->tx_midi_substreams[0]);
415                 if (substream)
416                         snd_rawmidi_receive(substream, &byte, 1);
417         }
418 }
419 
420 const struct snd_ff_protocol snd_ff_protocol_ff800 = {
421         .handle_msg             = ff800_handle_midi_msg,
422         .fill_midi_msg          = former_fill_midi_msg,
423         .get_clock              = former_get_clock,
424         .switch_fetching_mode   = former_switch_fetching_mode,
425         .allocate_resources     = ff800_allocate_resources,
426         .begin_session          = ff800_begin_session,
427         .finish_session         = ff800_finish_session,
428         .dump_status            = former_dump_status,
429 };
430 
431 #define FF400_STF               0x000080100500ull
432 #define FF400_RX_PACKET_FORMAT  0x000080100504ull
433 #define FF400_ISOC_COMM_START   0x000080100508ull
434 #define FF400_TX_PACKET_FORMAT  0x00008010050cull
435 #define FF400_ISOC_COMM_STOP    0x000080100510ull
436 
437 // Fireface 400 manages isochronous channel number in 3 bit field. Therefore,
438 // we can allocate between 0 and 7 channel.
439 static int ff400_allocate_resources(struct snd_ff *ff, unsigned int rate)
440 {
441         __le32 reg;
442         enum snd_ff_stream_mode mode;
443         int i;
444         int err;
445 
446         // Check whether the given value is supported or not.
447         for (i = 0; i < CIP_SFC_COUNT; i++) {
448                 if (amdtp_rate_table[i] == rate)
449                         break;
450         }
451         if (i >= CIP_SFC_COUNT)
452                 return -EINVAL;
453 
454         // Set the number of data blocks transferred in a second.
455         reg = cpu_to_le32(rate);
456         err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
457                                  FF400_STF, &reg, sizeof(reg), 0);
458         if (err < 0)
459                 return err;
460 
461         msleep(100);
462 
463         err = snd_ff_stream_get_multiplier_mode(i, &mode);
464         if (err < 0)
465                 return err;
466 
467         // Keep resources for in-stream.
468         ff->tx_resources.channels_mask = 0x00000000000000ffuLL;
469         err = fw_iso_resources_allocate(&ff->tx_resources,
470                         amdtp_stream_get_max_payload(&ff->tx_stream),
471                         fw_parent_device(ff->unit)->max_speed);
472         if (err < 0)
473                 return err;
474 
475         // Keep resources for out-stream.
476         ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
477         err = fw_iso_resources_allocate(&ff->rx_resources,
478                         amdtp_stream_get_max_payload(&ff->rx_stream),
479                         fw_parent_device(ff->unit)->max_speed);
480         if (err < 0)
481                 fw_iso_resources_free(&ff->tx_resources);
482 
483         return err;
484 }
485 
486 static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
487 {
488         unsigned int generation = ff->rx_resources.generation;
489         __le32 reg;
490         int err;
491 
492         if (generation != fw_parent_device(ff->unit)->card->generation) {
493                 err = fw_iso_resources_update(&ff->tx_resources);
494                 if (err < 0)
495                         return err;
496 
497                 err = fw_iso_resources_update(&ff->rx_resources);
498                 if (err < 0)
499                         return err;
500         }
501 
502         // Set isochronous channel and the number of quadlets of received
503         // packets.
504         reg = cpu_to_le32(((ff->rx_stream.data_block_quadlets << 3) << 8) |
505                           ff->rx_resources.channel);
506         err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
507                                  FF400_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);
508         if (err < 0)
509                 return err;
510 
511         // Set isochronous channel and the number of quadlets of transmitted
512         // packet.
513         // TODO: investigate the purpose of this 0x80.
514         reg = cpu_to_le32((0x80 << 24) |
515                           (ff->tx_resources.channel << 5) |
516                           (ff->tx_stream.data_block_quadlets));
517         err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
518                                  FF400_TX_PACKET_FORMAT, &reg, sizeof(reg), 0);
519         if (err < 0)
520                 return err;
521 
522         // Allow to transmit packets.
523         reg = cpu_to_le32(0x00000001);
524         return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
525                                  FF400_ISOC_COMM_START, &reg, sizeof(reg), 0);
526 }
527 
528 static void ff400_finish_session(struct snd_ff *ff)
529 {
530         __le32 reg;
531 
532         reg = cpu_to_le32(0x80000000);
533         snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
534                            FF400_ISOC_COMM_STOP, &reg, sizeof(reg), 0);
535 }
536 
537 static void parse_midi_msg(struct snd_ff *ff, u32 quad, unsigned int port)
538 {
539         struct snd_rawmidi_substream *substream = READ_ONCE(ff->tx_midi_substreams[port]);
540 
541         if (substream != NULL) {
542                 u8 byte = (quad >> (16 * port)) & 0x000000ff;
543 
544                 snd_rawmidi_receive(substream, &byte, 1);
545         }
546 }
547 
548 #define FF400_QUEUE_SIZE        32
549 
550 struct ff400_msg_parser {
551         struct {
552                 u32 msg;
553                 u32 tstamp;
554         } msgs[FF400_QUEUE_SIZE];
555         size_t push_pos;
556         size_t pull_pos;
557 };
558 
559 static bool ff400_has_msg(struct snd_ff *ff)
560 {
561         struct ff400_msg_parser *parser = ff->msg_parser;
562 
563         return (parser->push_pos != parser->pull_pos);
564 }
565 
566 // For Fireface 400, lower 4 bytes of destination address is configured by bit
567 // flag in quadlet register (little endian) at 0x'0000'801'0051c. Drivers can
568 // select one of 4 options:
569 //
570 // bit flags: offset of destination address
571 //  - 0x04000000: 0x'....'....'0000'0000
572 //  - 0x08000000: 0x'....'....'0000'0080
573 //  - 0x10000000: 0x'....'....'0000'0100
574 //  - 0x20000000: 0x'....'....'0000'0180
575 //
576 // Drivers can suppress the device to transfer asynchronous transactions by
577 // using below 2 bits.
578 //  - 0x01000000: suppress transmission
579 //  - 0x02000000: suppress transmission
580 //
581 // Actually, the register is write-only and includes the other options such as
582 // input attenuation. This driver allocates destination address with '0000'0000
583 // in its lower offset and expects userspace application to configure the
584 // register for it.
585 
586 // When the message is for signal level operation, the upper 4 bits in MSB expresses the pair of
587 // stereo physical port.
588 // - 0: Microphone input 0/1
589 // - 1: Line input 0/1
590 // - [2-4]: Line output 0-5
591 // - 5: Headphone output 0/1
592 // - 6: S/PDIF output 0/1
593 // - [7-10]: ADAT output 0-7
594 //
595 // The value of signal level can be detected by mask of 0x00fffc00. For signal level of microphone
596 // input:
597 //
598 // - 0:    0.0 dB
599 // - 10: +10.0 dB
600 // - 11: +11.0 dB
601 // - 12: +12.0 dB
602 // - ...
603 // - 63: +63.0 dB:
604 // - 64: +64.0 dB:
605 // - 65: +65.0 dB:
606 //
607 // For signal level of line input:
608 //
609 // - 0:  0.0 dB
610 // - 1: +0.5 dB
611 // - 2: +1.0 dB
612 // - 3: +1.5 dB
613 // - ...
614 // - 34: +17.0 dB:
615 // - 35: +17.5 dB:
616 // - 36: +18.0 dB:
617 //
618 // For signal level of any type of output:
619 //
620 // - 63: -infinite
621 // - 62: -58.0 dB
622 // - 61: -56.0 dB
623 // - 60: -54.0 dB
624 // - 59: -53.0 dB
625 // - 58: -52.0 dB
626 // - ...
627 // - 7: -1.0 dB
628 // - 6:  0.0 dB
629 // - 5: +1.0 dB
630 // - ...
631 // - 2: +4.0 dB
632 // - 1: +5.0 dB
633 // - 0: +6.0 dB
634 //
635 // When the message is not for signal level operation, it's for MIDI bytes. When matching to
636 // FF400_MSG_FLAG_IS_MIDI_PORT_0, one MIDI byte can be detected by mask of 0x000000ff. When
637 // matching to FF400_MSG_FLAG_IS_MIDI_PORT_1, one MIDI byte can be detected by mask of 0x00ff0000.
638 #define FF400_MSG_FLAG_IS_SIGNAL_LEVEL          0x04000000
639 #define  FF400_MSG_FLAG_IS_RIGHT_CHANNEL        0x08000000
640 #define  FF400_MSG_FLAG_IS_STEREO_PAIRED        0x02000000
641 #define  FF400_MSG_MASK_STEREO_PAIR             0xf0000000
642 #define  FF400_MSG_MASK_SIGNAL_LEVEL            0x00fffc00
643 #define FF400_MSG_FLAG_IS_MIDI_PORT_0           0x00000100
644 #define  FF400_MSG_MASK_MIDI_PORT_0             0x000000ff
645 #define FF400_MSG_FLAG_IS_MIDI_PORT_1           0x01000000
646 #define  FF400_MSG_MASK_MIDI_PORT_1             0x00ff0000
647 
648 static void ff400_handle_msg(struct snd_ff *ff, unsigned int offset, const __le32 *buf,
649                              size_t length, u32 tstamp)
650 {
651         bool need_hwdep_wake_up = false;
652         int i;
653 
654         for (i = 0; i < length / 4; i++) {
655                 u32 quad = le32_to_cpu(buf[i]);
656 
657                 if (quad & FF400_MSG_FLAG_IS_SIGNAL_LEVEL) {
658                         struct ff400_msg_parser *parser = ff->msg_parser;
659 
660                         parser->msgs[parser->push_pos].msg = quad;
661                         parser->msgs[parser->push_pos].tstamp = tstamp;
662                         ++parser->push_pos;
663                         if (parser->push_pos >= FF400_QUEUE_SIZE)
664                                 parser->push_pos = 0;
665 
666                         need_hwdep_wake_up = true;
667                 } else if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_0) {
668                         parse_midi_msg(ff, quad, 0);
669                 } else if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_1) {
670                         parse_midi_msg(ff, quad, 1);
671                 }
672         }
673 
674         if (need_hwdep_wake_up)
675                 wake_up(&ff->hwdep_wait);
676 }
677 
678 static long ff400_copy_msg_to_user(struct snd_ff *ff, char __user *buf, long count)
679 {
680         struct snd_firewire_event_ff400_message ev = {
681                 .type = SNDRV_FIREWIRE_EVENT_FF400_MESSAGE,
682                 .message_count = 0,
683         };
684         struct ff400_msg_parser *parser = ff->msg_parser;
685         long consumed = 0;
686         long ret = 0;
687 
688         if (count < sizeof(ev) || parser->pull_pos == parser->push_pos)
689                 return 0;
690 
691         count -= sizeof(ev);
692         consumed += sizeof(ev);
693 
694         while (count >= sizeof(*parser->msgs) && parser->pull_pos != parser->push_pos) {
695                 spin_unlock_irq(&ff->lock);
696                 if (copy_to_user(buf + consumed, parser->msgs + parser->pull_pos,
697                                  sizeof(*parser->msgs)))
698                         ret = -EFAULT;
699                 spin_lock_irq(&ff->lock);
700                 if (ret)
701                         return ret;
702 
703                 ++parser->pull_pos;
704                 if (parser->pull_pos >= FF400_QUEUE_SIZE)
705                         parser->pull_pos = 0;
706                 ++ev.message_count;
707                 count -= sizeof(*parser->msgs);
708                 consumed += sizeof(*parser->msgs);
709         }
710 
711         spin_unlock_irq(&ff->lock);
712         if (copy_to_user(buf, &ev, sizeof(ev)))
713                 ret = -EFAULT;
714         spin_lock_irq(&ff->lock);
715         if (ret)
716                 return ret;
717 
718         return consumed;
719 }
720 
721 const struct snd_ff_protocol snd_ff_protocol_ff400 = {
722         .msg_parser_size        = sizeof(struct ff400_msg_parser),
723         .has_msg                = ff400_has_msg,
724         .copy_msg_to_user       = ff400_copy_msg_to_user,
725         .handle_msg             = ff400_handle_msg,
726         .fill_midi_msg          = former_fill_midi_msg,
727         .get_clock              = former_get_clock,
728         .switch_fetching_mode   = former_switch_fetching_mode,
729         .allocate_resources     = ff400_allocate_resources,
730         .begin_session          = ff400_begin_session,
731         .finish_session         = ff400_finish_session,
732         .dump_status            = former_dump_status,
733 };
734 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php