Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5eb11d6b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 479459a8 64559311
Loading
Loading
Loading
Loading
+62 −9
Original line number Diff line number Diff line
@@ -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;
	}
+2 −3
Original line number Diff line number Diff line
@@ -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;
+0 −7
Original line number Diff line number Diff line
@@ -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;
}
+0 −5
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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 */