root/sound/firewire/fireface/ff-protocol-former.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parse_clock_bits
  2. former_get_clock
  3. former_switch_fetching_mode
  4. dump_clock_config
  5. dump_sync_status
  6. former_dump_status
  7. former_fill_midi_msg
  8. allocate_tx_resources
  9. ff800_allocate_resources
  10. ff800_begin_session
  11. ff800_finish_session
  12. ff800_handle_midi_msg
  13. ff400_allocate_resources
  14. ff400_begin_session
  15. ff400_finish_session
  16. ff400_handle_midi_msg

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

/* [<][>][^][v][top][bottom][index][help] */