Merge branch 'topic/firewire' into for-next
authorTakashi Iwai <tiwai@suse.de>
Tue, 18 May 2021 10:25:24 +0000 (12:25 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 18 May 2021 10:25:24 +0000 (12:25 +0200)
18 files changed:
sound/firewire/Kconfig
sound/firewire/amdtp-am824.c
sound/firewire/amdtp-am824.h
sound/firewire/amdtp-stream.c
sound/firewire/amdtp-stream.h
sound/firewire/bebob/bebob.c
sound/firewire/dice/dice-pcm.c
sound/firewire/dice/dice-stream.c
sound/firewire/dice/dice-tcelectronic.c
sound/firewire/dice/dice.c
sound/firewire/dice/dice.h
sound/firewire/digi00x/amdtp-dot.c
sound/firewire/motu/motu.h
sound/firewire/oxfw/oxfw-stream.c
sound/firewire/oxfw/oxfw.c
sound/firewire/oxfw/oxfw.h
sound/pci/hda/patch_realtek.c
sound/pci/intel8x0.c

index 9897bd2..def1f3d 100644 (file)
@@ -38,7 +38,7 @@ config SND_OXFW
           * Mackie(Loud) Onyx 1640i (former model)
           * Mackie(Loud) Onyx Satellite
           * Mackie(Loud) Tapco Link.Firewire
-          * Mackie(Loud) d.4 pro
+          * Mackie(Loud) d.2 pro/d.4 pro (built-in FireWire card with OXFW971 ASIC)
           * Mackie(Loud) U.420/U.420d
           * TASCAM FireOne
           * Stanton Controllers & Systems 1 Deck/Mixer
@@ -84,7 +84,7 @@ config SND_BEBOB
          * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
          * BridgeCo RDAudio1/Audio5
          * Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
-         * Mackie d.2 (FireWire Option) and d.2 Pro
+         * Mackie d.2 (optional FireWire card with DM1000 ASIC)
          * Stanton FinalScratch 2 (ScratchAmp)
          * Tascam IF-FW/DM
          * Behringer XENIX UFX 1204/1604
index fea92e1..d9c700f 100644 (file)
@@ -410,10 +410,10 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s,
  * @s: the AMDTP stream to initialize
  * @unit: the target of the stream
  * @dir: the direction of stream
- * @flags: the packet transmission method to use
+ * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants.
  */
 int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit,
-                    enum amdtp_stream_direction dir, enum cip_flags flags)
+                    enum amdtp_stream_direction dir, unsigned int flags)
 {
        amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
 
index 06d2807..2b092b1 100644 (file)
@@ -45,5 +45,5 @@ void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port,
                              struct snd_rawmidi_substream *midi);
 
 int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit,
-                    enum amdtp_stream_direction dir, enum cip_flags flags);
+                    enum amdtp_stream_direction dir, unsigned int flags);
 #endif
index e0faa66..409274a 100644 (file)
 #define IT_PKT_HEADER_SIZE_CIP         8 // For 2 CIP header.
 #define IT_PKT_HEADER_SIZE_NO_CIP      0 // Nothing.
 
+// The initial firmware of OXFW970 can postpone transmission of packet during finishing
+// asynchronous transaction. This module accepts 5 cycles to skip as maximum to avoid buffer
+// overrun. Actual device can skip more, then this module stops the packet streaming.
+#define IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES       5
+
 static void pcm_period_work(struct work_struct *work);
 
 /**
@@ -71,13 +76,13 @@ static void pcm_period_work(struct work_struct *work);
  * @s: the AMDTP stream to initialize
  * @unit: the target of the stream
  * @dir: the direction of stream
- * @flags: the packet transmission method to use
+ * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants.
  * @fmt: the value of fmt field in CIP header
  * @process_ctx_payloads: callback handler to process payloads of isoc context
  * @protocol_size: the size to allocate newly for protocol
  */
 int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
-                     enum amdtp_stream_direction dir, enum cip_flags flags,
+                     enum amdtp_stream_direction dir, unsigned int flags,
                      unsigned int fmt,
                      amdtp_stream_process_ctx_payloads_t process_ctx_payloads,
                      unsigned int protocol_size)
@@ -316,7 +321,7 @@ unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s)
        unsigned int cip_header_size = 0;
 
        if (s->flags & CIP_JUMBO_PAYLOAD)
-               multiplier = 5;
+               multiplier = IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES;
        if (!(s->flags & CIP_NO_HEADER))
                cip_header_size = sizeof(__be32) * 2;
 
index a3daa1f..0628b6e 100644 (file)
@@ -112,7 +112,8 @@ typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)(
 struct amdtp_domain;
 struct amdtp_stream {
        struct fw_unit *unit;
-       enum cip_flags flags;
+       // The combination of cip_flags enumeration-constants.
+       unsigned int flags;
        enum amdtp_stream_direction direction;
        struct mutex mutex;
 
@@ -184,7 +185,7 @@ struct amdtp_stream {
 };
 
 int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
-                     enum amdtp_stream_direction dir, enum cip_flags flags,
+                     enum amdtp_stream_direction dir, unsigned int flags,
                      unsigned int fmt,
                      amdtp_stream_process_ctx_payloads_t process_ctx_payloads,
                      unsigned int protocol_size);
index daeecfa..90e98a6 100644 (file)
@@ -387,7 +387,7 @@ static const struct ieee1394_device_id bebob_id_table[] = {
        SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal),
        /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */
        SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal),
-       // Mackie, d.2 (Firewire option card) and d.2 Pro (the card is built-in).
+       // Mackie, d.2 (optional Firewire card with DM1000).
        SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal),
        /* Stanton, ScratchAmp */
        SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal),
index af8a90e..a69ca11 100644 (file)
@@ -218,7 +218,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
 
                if (frames_per_period > 0) {
                        // For double_pcm_frame quirk.
-                       if (rate > 96000) {
+                       if (rate > 96000 && !dice->disable_double_pcm_frames) {
                                frames_per_period *= 2;
                                frames_per_buffer *= 2;
                        }
@@ -273,7 +273,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
 
                mutex_lock(&dice->mutex);
                // For double_pcm_frame quirk.
-               if (rate > 96000) {
+               if (rate > 96000 && !dice->disable_double_pcm_frames) {
                        events_per_period /= 2;
                        events_per_buffer /= 2;
                }
index 1a14c08..c4dfe76 100644 (file)
@@ -181,7 +181,7 @@ static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
        // as 'Dual Wire'.
        // For this quirk, blocking mode is required and PCM buffer size should
        // be aligned to SYT_INTERVAL.
-       double_pcm_frames = rate > 96000;
+       double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames);
        if (double_pcm_frames) {
                rate /= 2;
                pcm_chs *= 2;
index a8875d2..43a3bcb 100644 (file)
@@ -38,8 +38,8 @@ static const struct dice_tc_spec konnekt_24d = {
 };
 
 static const struct dice_tc_spec konnekt_live = {
-       .tx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
-       .rx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
+       .tx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
+       .rx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
        .has_midi = true,
 };
 
index 107a816..239d164 100644 (file)
@@ -21,6 +21,7 @@ MODULE_LICENSE("GPL v2");
 #define OUI_SSL                        0x0050c2        // Actually ID reserved by IEEE.
 #define OUI_PRESONUS           0x000a92
 #define OUI_HARMAN             0x000fd7
+#define OUI_AVID               0x00a07e
 
 #define DICE_CATEGORY_ID       0x04
 #define WEISS_CATEGORY_ID      0x00
@@ -222,6 +223,14 @@ static int dice_probe(struct fw_unit *unit,
                                (snd_dice_detect_formats_t)entry->driver_data;
        }
 
+       // Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer
+       // frequency.
+       // * Avid M-Box 3 Pro
+       // * M-Audio Profire 610
+       // * M-Audio Profire 2626
+       if (entry->vendor_id == OUI_MAUDIO || entry->vendor_id == OUI_AVID)
+               dice->disable_double_pcm_frames = true;
+
        spin_lock_init(&dice->lock);
        mutex_init(&dice->mutex);
        init_completion(&dice->clock_accepted);
@@ -278,7 +287,22 @@ static void dice_bus_reset(struct fw_unit *unit)
 
 #define DICE_INTERFACE 0x000001
 
+#define DICE_DEV_ENTRY_TYPICAL(vendor, model, data) \
+       { \
+               .match_flags    = IEEE1394_MATCH_VENDOR_ID | \
+                                 IEEE1394_MATCH_MODEL_ID | \
+                                 IEEE1394_MATCH_SPECIFIER_ID | \
+                                 IEEE1394_MATCH_VERSION, \
+               .vendor_id      = (vendor), \
+               .model_id       = (model), \
+               .specifier_id   = (vendor), \
+               .version        = DICE_INTERFACE, \
+               .driver_data = (kernel_ulong_t)(data), \
+       }
+
 static const struct ieee1394_device_id dice_id_table[] = {
+       // Avid M-Box 3 Pro. To match in probe function.
+       DICE_DEV_ENTRY_TYPICAL(OUI_AVID, 0x000004, snd_dice_detect_extension_formats),
        /* M-Audio Profire 2626 has a different value in version field. */
        {
                .match_flags    = IEEE1394_MATCH_VENDOR_ID |
index adc6f7c..3c967d1 100644 (file)
@@ -109,7 +109,8 @@ struct snd_dice {
        struct fw_iso_resources rx_resources[MAX_STREAMS];
        struct amdtp_stream tx_stream[MAX_STREAMS];
        struct amdtp_stream rx_stream[MAX_STREAMS];
-       bool global_enabled;
+       bool global_enabled:1;
+       bool disable_double_pcm_frames:1;
        struct completion clock_accepted;
        unsigned int substreams_counter;
 
index d613642..398c57a 100644 (file)
@@ -396,7 +396,7 @@ int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit,
                 enum amdtp_stream_direction dir)
 {
        amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
-       enum cip_flags flags;
+       unsigned int flags;
 
        // Use different mode between incoming/outgoing.
        if (dir == AMDTP_IN_STREAM) {
index 3d0236e..92effb6 100644 (file)
@@ -106,7 +106,8 @@ enum snd_motu_protocol_version {
 struct snd_motu_spec {
        const char *const name;
        enum snd_motu_protocol_version protocol_version;
-       enum snd_motu_spec_flags flags;
+       // The combination of snd_motu_spec_flags enumeration-constants.
+       unsigned int flags;
 
        unsigned char tx_fixed_pcm_chunks[3];
        unsigned char rx_fixed_pcm_chunks[3];
index 80c9dc1..e9b6a9f 100644 (file)
@@ -153,12 +153,23 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
        struct cmp_connection *conn;
        enum cmp_direction c_dir;
        enum amdtp_stream_direction s_dir;
+       unsigned int flags;
        int err;
 
+       if (!(oxfw->quirks & SND_OXFW_QUIRK_BLOCKING_TRANSMISSION))
+               flags = CIP_NONBLOCKING;
+       else
+               flags = CIP_BLOCKING;
+
        if (stream == &oxfw->tx_stream) {
                conn = &oxfw->out_conn;
                c_dir = CMP_OUTPUT;
                s_dir = AMDTP_IN_STREAM;
+
+               if (oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD)
+                       flags |= CIP_JUMBO_PAYLOAD;
+               if (oxfw->quirks & SND_OXFW_QUIRK_WRONG_DBS)
+                       flags |= CIP_WRONG_DBS;
        } else {
                conn = &oxfw->in_conn;
                c_dir = CMP_INPUT;
@@ -169,24 +180,12 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
        if (err < 0)
                return err;
 
-       err = amdtp_am824_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING);
+       err = amdtp_am824_init(stream, oxfw->unit, s_dir, flags);
        if (err < 0) {
                cmp_connection_destroy(conn);
                return err;
        }
 
-       /*
-        * OXFW starts to transmit packets with non-zero dbc.
-        * OXFW postpone transferring packets till handling any asynchronous
-        * packets. As a result, next isochronous packet includes more data
-        * blocks than IEC 61883-6 defines.
-        */
-       if (stream == &oxfw->tx_stream) {
-               oxfw->tx_stream.flags |= CIP_JUMBO_PAYLOAD;
-               if (oxfw->wrong_dbs)
-                       oxfw->tx_stream.flags |= CIP_WRONG_DBS;
-       }
-
        return 0;
 }
 
index 9eea25c..59bffa3 100644 (file)
@@ -23,6 +23,8 @@
 #define OUI_APOGEE             0x0003db
 
 #define MODEL_SATELLITE                0x00200f
+#define MODEL_SCS1M            0x001000
+#define MODEL_DUET_FW          0x01dddd
 
 #define SPECIFIER_1394TA       0x00a02d
 #define VERSION_AVC            0x010001
@@ -46,8 +48,6 @@ static bool detect_loud_models(struct fw_unit *unit)
                "Onyx-i",
                "Onyx 1640i",
                "d.Pro",
-               "Mackie Onyx Satellite",
-               "Tapco LINK.firewire 4x6",
                "U.420"};
        char model[32];
        int err;
@@ -88,6 +88,9 @@ static int name_card(struct snd_oxfw *oxfw)
                goto end;
        be32_to_cpus(&firmware);
 
+       if (firmware >> 20 == 0x970)
+               oxfw->quirks |= SND_OXFW_QUIRK_JUMBO_PAYLOAD;
+
        /* to apply card definitions */
        if (oxfw->entry->vendor_id == VENDOR_GRIFFIN ||
            oxfw->entry->vendor_id == VENDOR_LACIE) {
@@ -143,13 +146,19 @@ static int detect_quirks(struct snd_oxfw *oxfw)
         * messages.
         */
        if (oxfw->entry->vendor_id == OUI_STANTON) {
-               /* No physical MIDI ports. */
+               if (oxfw->entry->model_id == MODEL_SCS1M)
+                       oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION;
+
+               // No physical MIDI ports.
                oxfw->midi_input_ports = 0;
                oxfw->midi_output_ports = 0;
 
                return snd_oxfw_scs1x_add(oxfw);
        }
 
+       if (oxfw->entry->vendor_id == OUI_APOGEE && oxfw->entry->model_id == MODEL_DUET_FW)
+               oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION;
+
        /*
         * TASCAM FireOne has physical control and requires a pair of additional
         * MIDI ports.
@@ -175,7 +184,7 @@ static int detect_quirks(struct snd_oxfw *oxfw)
         * value in 'dbs' field of CIP header against its format information.
         */
        if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE)
-               oxfw->wrong_dbs = true;
+               oxfw->quirks |= SND_OXFW_QUIRK_WRONG_DBS;
 
        return 0;
 }
@@ -245,7 +254,7 @@ static int oxfw_probe(struct fw_unit *unit,
 {
        struct snd_oxfw *oxfw;
 
-       if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit))
+       if (entry->vendor_id == VENDOR_LOUD && entry->model_id == 0 && !detect_loud_models(unit))
                return -ENODEV;
 
        /* Allocate this independent of sound card instance. */
@@ -320,81 +329,67 @@ static const struct compat_info lacie_speakers = {
        .model_name = "FireWire Speakers",
 };
 
+#define OXFW_DEV_ENTRY(vendor, model, data) \
+{ \
+       .match_flags  = IEEE1394_MATCH_VENDOR_ID | \
+                       IEEE1394_MATCH_MODEL_ID | \
+                       IEEE1394_MATCH_SPECIFIER_ID | \
+                       IEEE1394_MATCH_VERSION, \
+       .vendor_id    = vendor, \
+       .model_id     = model, \
+       .specifier_id = SPECIFIER_1394TA, \
+       .version      = VERSION_AVC, \
+       .driver_data  = (kernel_ulong_t)data, \
+}
+
 static const struct ieee1394_device_id oxfw_id_table[] = {
-       {
-               .match_flags  = IEEE1394_MATCH_VENDOR_ID |
-                               IEEE1394_MATCH_MODEL_ID |
-                               IEEE1394_MATCH_SPECIFIER_ID |
-                               IEEE1394_MATCH_VERSION,
-               .vendor_id    = VENDOR_GRIFFIN,
-               .model_id     = 0x00f970,
-               .specifier_id = SPECIFIER_1394TA,
-               .version      = VERSION_AVC,
-               .driver_data  = (kernel_ulong_t)&griffin_firewave,
-       },
-       {
-               .match_flags  = IEEE1394_MATCH_VENDOR_ID |
-                               IEEE1394_MATCH_MODEL_ID |
-                               IEEE1394_MATCH_SPECIFIER_ID |
-                               IEEE1394_MATCH_VERSION,
-               .vendor_id    = VENDOR_LACIE,
-               .model_id     = 0x00f970,
-               .specifier_id = SPECIFIER_1394TA,
-               .version      = VERSION_AVC,
-               .driver_data  = (kernel_ulong_t)&lacie_speakers,
-       },
-       /* Behringer,F-Control Audio 202 */
-       {
-               .match_flags    = IEEE1394_MATCH_VENDOR_ID |
-                                 IEEE1394_MATCH_MODEL_ID,
-               .vendor_id      = VENDOR_BEHRINGER,
-               .model_id       = 0x00fc22,
-       },
-       /*
-        * Any Mackie(Loud) models (name string/model id):
-        *  Onyx-i series (former models):      0x081216
-        *  Mackie Onyx Satellite:              0x00200f
-        *  Tapco LINK.firewire 4x6:            0x000460
-        *  d.4 pro:                            Unknown
-        *  U.420:                              Unknown
-        *  U.420d:                             Unknown
-        */
+       //
+       // OXFW970 devices:
+       // Initial firmware has a quirk to postpone isoc packet transmission during finishing async
+       // transaction. As a result, several isochronous cycles are skipped to transfer the packets
+       // and the audio data frames which should have been transferred during the cycles are put
+       // into packet at the first isoc cycle after the postpone. Furthermore, the value of SYT
+       // field in CIP header is not reliable as synchronization timing,
+       //
+       OXFW_DEV_ENTRY(VENDOR_GRIFFIN, 0x00f970, &griffin_firewave),
+       OXFW_DEV_ENTRY(VENDOR_LACIE, 0x00f970, &lacie_speakers),
+       // Behringer,F-Control Audio 202. The value of SYT field is not reliable at all.
+       OXFW_DEV_ENTRY(VENDOR_BEHRINGER, 0x00fc22, NULL),
+       // Loud Technologies, Tapco Link.FireWire 4x6. The value of SYT field is always 0xffff.
+       OXFW_DEV_ENTRY(VENDOR_LOUD, 0x000460, NULL),
+       // Loud Technologies, Mackie Onyx Satellite. Although revised version of firmware is
+       // installed to avoid the postpone, the value of SYT field is always 0xffff.
+       OXFW_DEV_ENTRY(VENDOR_LOUD, MODEL_SATELLITE, NULL),
+       // Miglia HarmonyAudio. Not yet identified.
+
+       //
+       // OXFW971 devices:
+       // The value of SYT field in CIP header is enough reliable. Both of blocking and non-blocking
+       // transmission methods are available.
+       //
+       // Any Mackie(Loud) models (name string/model id):
+       //  Onyx-i series (former models):      0x081216
+       //  Onyx 1640i:                         0x001640
+       //  d.2 pro/d.4 pro (built-in card):    Unknown
+       //  U.420:                              Unknown
+       //  U.420d:                             Unknown
        {
                .match_flags    = IEEE1394_MATCH_VENDOR_ID |
                                  IEEE1394_MATCH_SPECIFIER_ID |
                                  IEEE1394_MATCH_VERSION,
                .vendor_id      = VENDOR_LOUD,
+               .model_id       = 0,
                .specifier_id   = SPECIFIER_1394TA,
                .version        = VERSION_AVC,
        },
-       /* TASCAM, FireOne */
-       {
-               .match_flags    = IEEE1394_MATCH_VENDOR_ID |
-                                 IEEE1394_MATCH_MODEL_ID,
-               .vendor_id      = VENDOR_TASCAM,
-               .model_id       = 0x800007,
-       },
-       /* Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m) */
-       {
-               .match_flags    = IEEE1394_MATCH_VENDOR_ID |
-                                 IEEE1394_MATCH_MODEL_ID,
-               .vendor_id      = OUI_STANTON,
-               .model_id       = 0x001000,
-       },
-       /* Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d) */
-       {
-               .match_flags    = IEEE1394_MATCH_VENDOR_ID |
-                                 IEEE1394_MATCH_MODEL_ID,
-               .vendor_id      = OUI_STANTON,
-               .model_id       = 0x002000,
-       },
-       // APOGEE, duet FireWire
-       {
-               .match_flags    = IEEE1394_MATCH_VENDOR_ID |
-                                 IEEE1394_MATCH_MODEL_ID,
-               .vendor_id      = OUI_APOGEE,
-               .model_id       = 0x01dddd,
-       },
+       // TASCAM, FireOne.
+       OXFW_DEV_ENTRY(VENDOR_TASCAM, 0x800007, NULL),
+       // Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m).
+       OXFW_DEV_ENTRY(OUI_STANTON, MODEL_SCS1M, NULL),
+       // Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d).
+       OXFW_DEV_ENTRY(OUI_STANTON, 0x002000, NULL),
+       // APOGEE, duet FireWire.
+       OXFW_DEV_ENTRY(OUI_APOGEE, MODEL_DUET_FW, NULL),
        { }
 };
 MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table);
index fa2d7f9..853135b 100644 (file)
 #include "../amdtp-am824.h"
 #include "../cmp.h"
 
+enum snd_oxfw_quirk {
+       // Postpone transferring packets during handling asynchronous transaction. As a result,
+       // next isochronous packet includes more events than one packet can include.
+       SND_OXFW_QUIRK_JUMBO_PAYLOAD = 0x01,
+       // The dbs field of CIP header in tx packet is wrong.
+       SND_OXFW_QUIRK_WRONG_DBS = 0x02,
+       // Blocking transmission mode is used.
+       SND_OXFW_QUIRK_BLOCKING_TRANSMISSION = 0x04,
+};
+
 /* This is an arbitrary number for convinience. */
 #define        SND_OXFW_STREAM_FORMAT_ENTRIES  10
 struct snd_oxfw {
@@ -43,7 +53,8 @@ struct snd_oxfw {
        bool registered;
        struct delayed_work dwork;
 
-       bool wrong_dbs;
+       // The combination of snd_oxfw_quirk enumeration-constants.
+       unsigned int quirks;
        bool has_output;
        bool has_input;
        u8 *tx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES];
index 3e269de..552e2cb 100644 (file)
@@ -8385,12 +8385,19 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f2, "Clevo NH50E[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f5, "Clevo NH55EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f6, "Clevo NH55DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f3, "Clevo NH77DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -8408,9 +8415,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x9600, "Clevo N960K[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL5XNU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xc018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xc019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xc022, "Clevo NH77[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
        SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
index 4f31653..abc710a 100644 (file)
@@ -331,6 +331,7 @@ struct ichdev {
        unsigned int ali_slot;                  /* ALI DMA slot */
        struct ac97_pcm *pcm;
        int pcm_open_flag;
+       unsigned int prepared:1;
        unsigned int suspended: 1;
 };
 
@@ -691,6 +692,9 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich
        int status, civ, i, step;
        int ack = 0;
 
+       if (!ichdev->prepared || ichdev->suspended)
+               return;
+
        spin_lock_irqsave(&chip->reg_lock, flags);
        status = igetbyte(chip, port + ichdev->roff_sr);
        civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
@@ -881,6 +885,7 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
        if (ichdev->pcm_open_flag) {
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
+               ichdev->prepared = 0;
        }
        err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
                                params_channels(hw_params),
@@ -902,6 +907,7 @@ static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
        if (ichdev->pcm_open_flag) {
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
+               ichdev->prepared = 0;
        }
        return 0;
 }
@@ -976,6 +982,7 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
                        ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
        }
        snd_intel8x0_setup_periods(chip, ichdev);
+       ichdev->prepared = 1;
        return 0;
 }