forked from luck/tmp_suning_uos_patched
sound fixes for 3.19-rc6
This batch contains two fixes for FireWire lib module and a quirk for yet another Logitech WebCam. The former is the fixes for MIDI handling I forgot to pick up during the merge window. All the fixed code is pretty local and shouldn't give any regressions. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJUvmi/AAoJEGwxgFQ9KSmkg3cQAK3z0rEzmlTvQUVkLlLnfQwo C2m4e0yIfyzpv7+AkWarTzD6zteiaPMQR02RMYgDu8Zq7a6eqFhc1lDM3wOElOl1 uW1YwnH3n+JTywdgBR8CdjTP52CmgyIcrQkXeEnAyqC329XpgTfRY0Ckkbt3GGyN doK94jaLD8x399XoMiBrUuSc6oS7bbRxKa6xWTluMSGTTmWsdtMZpPIl5TdpL2/G z/gycBJcMJO8El6anZQndQgMKePZWrM74lDvHTn3dNQuF3cjOaKP1oc5/VG5iZU0 XLVr8koEBMPZ+4D3MzRBYCru39aUsAZNKFP/+2MnS7Y9Q8mY6kt5j0qYUy0UXAcL TTI9R/iEr9ZyXreBOJsQWhQCIp4LamSC9pVwtCQ0MPz7V5O8NA0PdLT/02rho0v2 B/oUNrEoW6iE0qIfCl94/vO6hu7oUBjC/p+BqYsj6Yuev9TH2IfLX6uqU1dIt+Ee UfZpd6mhodrmxqPWcL8qK0PbyiiIrEyi8ahmcRFLJnOcYtIABngJGYd4eyUnIsJu seIZK+lg4kFhIC++zyqJjoZ9mU2RxUzKlP/JJD4U+WTpPvvBPW+KYmOp8z7rdH85 eNWE+TqpMHdKM+bBxoSvxFO7L7e0uLjrx628hNhjvvYQFUZmqTgf9jB7DX7hkTKA mzmVqUB3qCEacIWm6IQl =HKNt -----END PGP SIGNATURE----- Merge tag 'sound-3.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "This batch contains two fixes for FireWire lib module and a quirk for yet another Logitech WebCam. The former is the fixes for MIDI handling I forgot to pick up during the merge window. All the fixed code is pretty local and shouldn't give any regressions" * tag 'sound-3.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: usb-audio: Add mic volume fix quirk for Logitech Webcam C210 ALSA: firewire-lib: limit the MIDI data rate ALSA: firewire-lib: remove rx_blocks_for_midi quirk
This commit is contained in:
commit
5eb11d6b3f
@ -21,7 +21,19 @@
|
||||
#define CYCLES_PER_SECOND 8000
|
||||
#define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND)
|
||||
|
||||
#define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */
|
||||
/*
|
||||
* Nominally 3125 bytes/second, but the MIDI port's clock might be
|
||||
* 1% too slow, and the bus clock 100 ppm too fast.
|
||||
*/
|
||||
#define MIDI_BYTES_PER_SECOND 3093
|
||||
|
||||
/*
|
||||
* Several devices look only at the first eight data blocks.
|
||||
* In any case, this is more than enough for the MIDI data rate.
|
||||
*/
|
||||
#define MAX_MIDI_RX_BLOCKS 8
|
||||
|
||||
#define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */
|
||||
|
||||
/* isochronous header parameters */
|
||||
#define ISO_DATA_LENGTH_SHIFT 16
|
||||
@ -78,8 +90,6 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
|
||||
s->callbacked = false;
|
||||
s->sync_slave = NULL;
|
||||
|
||||
s->rx_blocks_for_midi = UINT_MAX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(amdtp_stream_init);
|
||||
@ -222,6 +232,14 @@ void amdtp_stream_set_parameters(struct amdtp_stream *s,
|
||||
for (i = 0; i < pcm_channels; i++)
|
||||
s->pcm_positions[i] = i;
|
||||
s->midi_position = s->pcm_channels;
|
||||
|
||||
/*
|
||||
* We do not know the actual MIDI FIFO size of most devices. Just
|
||||
* assume two bytes, i.e., one byte can be received over the bus while
|
||||
* the previous one is transmitted over MIDI.
|
||||
* (The value here is adjusted for midi_ratelimit_per_packet().)
|
||||
*/
|
||||
s->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1;
|
||||
}
|
||||
EXPORT_SYMBOL(amdtp_stream_set_parameters);
|
||||
|
||||
@ -463,6 +481,36 @@ static void amdtp_fill_pcm_silence(struct amdtp_stream *s,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid sending MIDI bytes at too high a rate, assume that the receiving
|
||||
* device has a FIFO, and track how much it is filled. This values increases
|
||||
* by one whenever we send one byte in a packet, but the FIFO empties at
|
||||
* a constant rate independent of our packet rate. One packet has syt_interval
|
||||
* samples, so the number of bytes that empty out of the FIFO, per packet(!),
|
||||
* is MIDI_BYTES_PER_SECOND * syt_interval / sample_rate. To avoid storing
|
||||
* fractional values, the values in midi_fifo_used[] are measured in bytes
|
||||
* multiplied by the sample rate.
|
||||
*/
|
||||
static bool midi_ratelimit_per_packet(struct amdtp_stream *s, unsigned int port)
|
||||
{
|
||||
int used;
|
||||
|
||||
used = s->midi_fifo_used[port];
|
||||
if (used == 0) /* common shortcut */
|
||||
return true;
|
||||
|
||||
used -= MIDI_BYTES_PER_SECOND * s->syt_interval;
|
||||
used = max(used, 0);
|
||||
s->midi_fifo_used[port] = used;
|
||||
|
||||
return used < s->midi_fifo_limit;
|
||||
}
|
||||
|
||||
static void midi_rate_use_one_byte(struct amdtp_stream *s, unsigned int port)
|
||||
{
|
||||
s->midi_fifo_used[port] += amdtp_rate_table[s->sfc];
|
||||
}
|
||||
|
||||
static void amdtp_fill_midi(struct amdtp_stream *s,
|
||||
__be32 *buffer, unsigned int frames)
|
||||
{
|
||||
@ -470,16 +518,21 @@ static void amdtp_fill_midi(struct amdtp_stream *s,
|
||||
u8 *b;
|
||||
|
||||
for (f = 0; f < frames; f++) {
|
||||
buffer[s->midi_position] = 0;
|
||||
b = (u8 *)&buffer[s->midi_position];
|
||||
|
||||
port = (s->data_block_counter + f) % 8;
|
||||
if ((f >= s->rx_blocks_for_midi) ||
|
||||
(s->midi[port] == NULL) ||
|
||||
(snd_rawmidi_transmit(s->midi[port], b + 1, 1) <= 0))
|
||||
b[0] = 0x80;
|
||||
else
|
||||
if (f < MAX_MIDI_RX_BLOCKS &&
|
||||
midi_ratelimit_per_packet(s, port) &&
|
||||
s->midi[port] != NULL &&
|
||||
snd_rawmidi_transmit(s->midi[port], &b[1], 1) == 1) {
|
||||
midi_rate_use_one_byte(s, port);
|
||||
b[0] = 0x81;
|
||||
} else {
|
||||
b[0] = 0x80;
|
||||
b[1] = 0;
|
||||
}
|
||||
b[2] = 0;
|
||||
b[3] = 0;
|
||||
|
||||
buffer += s->data_block_quadlets;
|
||||
}
|
||||
|
@ -148,13 +148,12 @@ struct amdtp_stream {
|
||||
bool double_pcm_frames;
|
||||
|
||||
struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
|
||||
int midi_fifo_limit;
|
||||
int midi_fifo_used[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
|
||||
|
||||
/* quirk: fixed interval of dbc between previos/current packets. */
|
||||
unsigned int tx_dbc_interval;
|
||||
|
||||
/* quirk: the first count of data blocks in an rx packet for MIDI */
|
||||
unsigned int rx_blocks_for_midi;
|
||||
|
||||
bool callbacked;
|
||||
wait_queue_head_t callback_wait;
|
||||
struct amdtp_stream *sync_slave;
|
||||
|
@ -484,13 +484,6 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob)
|
||||
amdtp_stream_destroy(&bebob->rx_stream);
|
||||
destroy_both_connections(bebob);
|
||||
}
|
||||
/*
|
||||
* The firmware for these devices ignore MIDI messages in more than
|
||||
* first 8 data blocks of an received AMDTP packet.
|
||||
*/
|
||||
if (bebob->spec == &maudio_fw410_spec ||
|
||||
bebob->spec == &maudio_special_spec)
|
||||
bebob->rx_stream.rx_blocks_for_midi = 8;
|
||||
end:
|
||||
return err;
|
||||
}
|
||||
|
@ -179,11 +179,6 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw)
|
||||
destroy_stream(efw, &efw->tx_stream);
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
* Fireworks ignores MIDI messages in more than first 8 data
|
||||
* blocks of an received AMDTP packet.
|
||||
*/
|
||||
efw->rx_stream.rx_blocks_for_midi = 8;
|
||||
|
||||
/* set IEC61883 compliant mode (actually not fully compliant...) */
|
||||
err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883);
|
||||
|
@ -913,6 +913,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
|
||||
case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */
|
||||
case USB_ID(0x046d, 0x0808):
|
||||
case USB_ID(0x046d, 0x0809):
|
||||
case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */
|
||||
case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
|
||||
case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
|
||||
case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */
|
||||
|
Loading…
Reference in New Issue
Block a user