These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / sound / firewire / oxfw / oxfw-stream.c
index e6757cd..7cb5743 100644 (file)
@@ -148,14 +148,17 @@ static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream,
        }
 
        pcm_channels = formation.pcm;
-       midi_ports = DIV_ROUND_UP(formation.midi, 8);
+       midi_ports = formation.midi * 8;
 
        /* The stream should have one pcm channels at least */
        if (pcm_channels == 0) {
                err = -EINVAL;
                goto end;
        }
-       amdtp_stream_set_parameters(stream, rate, pcm_channels, midi_ports);
+       err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports,
+                                        false);
+       if (err < 0)
+               goto end;
 
        err = cmp_connection_establish(conn,
                                       amdtp_stream_get_max_payload(stream));
@@ -225,16 +228,25 @@ int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw,
        if (err < 0)
                goto end;
 
-       err = amdtp_stream_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING);
+       err = amdtp_am824_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING);
        if (err < 0) {
                amdtp_stream_destroy(stream);
                cmp_connection_destroy(conn);
                goto end;
        }
 
-       /* OXFW starts to transmit packets with non-zero dbc. */
-       if (stream == &oxfw->tx_stream)
-               oxfw->tx_stream.flags |= CIP_SKIP_INIT_DBC_CHECK;
+       /*
+        * 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_SKIP_INIT_DBC_CHECK |
+                                        CIP_JUMBO_PAYLOAD;
+               if (oxfw->wrong_dbs)
+                       oxfw->tx_stream.flags |= CIP_WRONG_DBS;
+       }
 end:
        return err;
 }
@@ -474,8 +486,8 @@ int snd_oxfw_stream_parse_format(u8 *format,
                }
        }
 
-       if (formation->pcm  > AMDTP_MAX_CHANNELS_FOR_PCM ||
-           formation->midi > AMDTP_MAX_CHANNELS_FOR_MIDI)
+       if (formation->pcm  > AM824_MAX_CHANNELS_FOR_PCM ||
+           formation->midi > AM824_MAX_CHANNELS_FOR_MIDI)
                return -ENOSYS;
 
        return 0;
@@ -506,12 +518,11 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
        if (err < 0)
                goto end;
 
-       formats[eid] = kmalloc(*len, GFP_KERNEL);
+       formats[eid] = kmemdup(buf, *len, GFP_KERNEL);
        if (formats[eid] == NULL) {
                err = -ENOMEM;
                goto end;
        }
-       memcpy(formats[eid], buf, *len);
 
        /* apply the format for each available sampling rate */
        for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) {
@@ -525,12 +536,11 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
                        continue;
 
                eid++;
-               formats[eid] = kmalloc(*len, GFP_KERNEL);
+               formats[eid] = kmemdup(buf, *len, GFP_KERNEL);
                if (formats[eid] == NULL) {
                        err = -ENOMEM;
                        goto end;
                }
-               memcpy(formats[eid], buf, *len);
                formats[eid][2] = avc_stream_rate_table[i];
        }
 
@@ -588,12 +598,11 @@ static int fill_stream_formats(struct snd_oxfw *oxfw,
                if (err < 0)
                        break;
 
-               formats[eid] = kmalloc(len, GFP_KERNEL);
+               formats[eid] = kmemdup(buf, len, GFP_KERNEL);
                if (formats[eid] == NULL) {
                        err = -ENOMEM;
                        break;
                }
-               memcpy(formats[eid], buf, len);
 
                /* get next entry */
                len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
@@ -620,6 +629,9 @@ end:
 int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
 {
        u8 plugs[AVC_PLUG_INFO_BUF_BYTES];
+       struct snd_oxfw_stream_formation formation;
+       u8 *format;
+       unsigned int i;
        int err;
 
        /* the number of plugs for isoc in/out, ext in/out  */
@@ -639,12 +651,42 @@ int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
                err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_OUT, 0);
                if (err < 0)
                        goto end;
+
+               for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
+                       format = oxfw->tx_stream_formats[i];
+                       if (format == NULL)
+                               continue;
+                       err = snd_oxfw_stream_parse_format(format, &formation);
+                       if (err < 0)
+                               continue;
+
+                       /* Add one MIDI port. */
+                       if (formation.midi > 0)
+                               oxfw->midi_input_ports = 1;
+               }
+
                oxfw->has_output = true;
        }
 
        /* use iPCR[0] if exists */
-       if (plugs[0] > 0)
+       if (plugs[0] > 0) {
                err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
+               if (err < 0)
+                       goto end;
+
+               for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
+                       format = oxfw->rx_stream_formats[i];
+                       if (format == NULL)
+                               continue;
+                       err = snd_oxfw_stream_parse_format(format, &formation);
+                       if (err < 0)
+                               continue;
+
+                       /* Add one MIDI port. */
+                       if (formation.midi > 0)
+                               oxfw->midi_output_ports = 1;
+               }
+       }
 end:
        return err;
 }