@@ -545,10 +545,23 @@ static void parse_midi_msg(struct snd_ff *ff, u32 quad, unsigned int port)
545
545
}
546
546
}
547
547
548
- #define FF400_MSG_FLAG_IS_MIDI_PORT_0 0x00000100
549
- #define FF400_MSG_MASK_MIDI_PORT_0 0x000000ff
550
- #define FF400_MSG_FLAG_IS_MIDI_PORT_1 0x01000000
551
- #define FF400_MSG_MASK_MIDI_PORT_1 0x00ff0000
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
+ }
552
565
553
566
// For Fireface 400, lower 4 bytes of destination address is configured by bit
554
567
// flag in quadlet register (little endian) at 0x'0000'801'0051c. Drivers can
@@ -569,22 +582,140 @@ static void parse_midi_msg(struct snd_ff *ff, u32 quad, unsigned int port)
569
582
// input attenuation. This driver allocates destination address with '0000'0000
570
583
// in its lower offset and expects userspace application to configure the
571
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
+
572
648
static void ff400_handle_msg (struct snd_ff * ff , unsigned int offset , const __le32 * buf ,
573
649
size_t length , u32 tstamp )
574
650
{
651
+ bool need_hwdep_wake_up = false;
575
652
int i ;
576
653
577
654
for (i = 0 ; i < length / 4 ; i ++ ) {
578
655
u32 quad = le32_to_cpu (buf [i ]);
579
656
580
- if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_0 )
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 ) {
581
668
parse_midi_msg (ff , quad , 0 );
582
- else if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_1 )
669
+ } else if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_1 ) {
583
670
parse_midi_msg (ff , quad , 1 );
671
+ }
584
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 ff400_msg_parser * parser = ff -> msg_parser ;
681
+ u32 type = SNDRV_FIREWIRE_EVENT_FF400_MESSAGE ;
682
+ long consumed = 0 ;
683
+
684
+ if (count < 8 )
685
+ return 0 ;
686
+
687
+ spin_unlock_irq (& ff -> lock );
688
+
689
+ if (copy_to_user (buf , & type , sizeof (type )))
690
+ return - EFAULT ;
691
+
692
+ spin_lock_irq (& ff -> lock );
693
+
694
+ count -= sizeof (type );
695
+ consumed += sizeof (type );
696
+
697
+ while (count >= sizeof (* parser -> msgs ) && parser -> pull_pos != parser -> push_pos ) {
698
+ spin_unlock_irq (& ff -> lock );
699
+
700
+ if (copy_to_user (buf + consumed , parser -> msgs + parser -> pull_pos ,
701
+ sizeof (* parser -> msgs )))
702
+ return - EFAULT ;
703
+
704
+ spin_lock_irq (& ff -> lock );
705
+ ++ parser -> pull_pos ;
706
+ if (parser -> pull_pos >= FF400_QUEUE_SIZE )
707
+ parser -> pull_pos = 0 ;
708
+ count -= sizeof (* parser -> msgs );
709
+ consumed += sizeof (* parser -> msgs );
710
+ }
711
+
712
+ return consumed ;
585
713
}
586
714
587
715
const struct snd_ff_protocol snd_ff_protocol_ff400 = {
716
+ .msg_parser_size = sizeof (struct ff400_msg_parser ),
717
+ .has_msg = ff400_has_msg ,
718
+ .copy_msg_to_user = ff400_copy_msg_to_user ,
588
719
.handle_msg = ff400_handle_msg ,
589
720
.fill_midi_msg = former_fill_midi_msg ,
590
721
.get_clock = former_get_clock ,
0 commit comments