Commit bd107372 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai
Browse files

ALSA: firewire-motu: code refactoring to handle model specific switch for protocol v2



In MOTU FireWire series, devices which support protocol version 2 have
several types of hardware design to process audio data frames for isoc
packet. Roughly devices are categorized into three groups:
 - 828mkII
 - Traveler/896HD
 - UltraLite/8pre FireWire

Some bit flags in register addressed by 0x'ffff'f000'0b14
includes device-specific effects.

This commit cleanups implementation of protocol v2 in this point.

Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20191030080644.1704-6-o-takashi@sakamocchi.jp


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4b2079f8
Loading
Loading
Loading
Loading
+36 −36
Original line number Diff line number Diff line
@@ -12,10 +12,8 @@
#define  V2_CLOCK_RATE_SHIFT			3
#define  V2_CLOCK_SRC_MASK			0x00000007
#define  V2_CLOCK_SRC_SHIFT			0
#define  V2_CLOCK_TRAVELER_FETCH_DISABLE	0x04000000
#define  V2_CLOCK_TRAVELER_FETCH_ENABLE		0x03000000
#define  V2_CLOCK_8PRE_FETCH_DISABLE		0x02000000
#define  V2_CLOCK_8PRE_FETCH_ENABLE		0x00000000
#define  V2_CLOCK_FETCH_ENABLE			0x02000000
#define  V2_CLOCK_MODEL_SPECIFIC		0x04000000

#define V2_IN_OUT_CONF_OFFSET			0x0c04
#define  V2_OPT_OUT_IFACE_MASK			0x00000c00
@@ -73,11 +71,6 @@ static int v2_set_clock_rate(struct snd_motu *motu, unsigned int rate)
	data &= ~V2_CLOCK_RATE_MASK;
	data |= i << V2_CLOCK_RATE_SHIFT;

	if (motu->spec == &snd_motu_spec_traveler) {
		data &= ~V2_CLOCK_TRAVELER_FETCH_ENABLE;
		data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
	}

	reg = cpu_to_be32(data);
	return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, &reg,
					  sizeof(reg));
@@ -145,42 +138,49 @@ static int v2_get_clock_source(struct snd_motu *motu,

static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable)
{
	enum snd_motu_clock_source src;
	__be32 reg;
	u32 data;
	int err = 0;

	if (motu->spec == &snd_motu_spec_traveler ||
	    motu->spec == &snd_motu_spec_8pre) {
		err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET,
						&reg, sizeof(reg));
	// 828mkII implements Altera ACEX 1K EP1K30. Nothing to do.
	if (motu->spec == &snd_motu_spec_828mk2)
		return 0;

	err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, &reg,
					sizeof(reg));
	if (err < 0)
		return err;
	data = be32_to_cpu(reg);

		if (motu->spec == &snd_motu_spec_traveler) {
			data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE |
				  V2_CLOCK_TRAVELER_FETCH_ENABLE);
	err = get_clock_source(motu, data, &src);
	if (err < 0)
		return err;

	data &= ~(V2_CLOCK_FETCH_ENABLE | V2_CLOCK_MODEL_SPECIFIC);
	if (enable)
				data |= V2_CLOCK_TRAVELER_FETCH_ENABLE;
			else
				data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
		} else if (motu->spec == &snd_motu_spec_8pre) {
			data &= ~(V2_CLOCK_8PRE_FETCH_DISABLE |
				  V2_CLOCK_8PRE_FETCH_ENABLE);
		data |= V2_CLOCK_FETCH_ENABLE;

			if (enable)
				data |= V2_CLOCK_8PRE_FETCH_DISABLE;
			else
				data |= V2_CLOCK_8PRE_FETCH_ENABLE;
		}
	if (motu->spec->flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4) {
		// Expected for Traveler and 896HD, which implements Altera
		// Cyclone EP1C3.
		data |= V2_CLOCK_MODEL_SPECIFIC;
	} else {
		// For UltraLite and 8pre, which implements Xilinx Spartan
		// XC3S200.
		unsigned int rate;

		reg = cpu_to_be32(data);
		err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET,
						 &reg, sizeof(reg));
		err = get_clock_rate(data, &rate);
		if (err < 0)
			return err;

		if (src == SND_MOTU_CLOCK_SOURCE_SPH && rate > 48000)
			data |= V2_CLOCK_MODEL_SPECIFIC;
	}

	return err;
	reg = cpu_to_be32(data);
	return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, &reg,
					  sizeof(reg));
}

static void calculate_fixed_part(struct snd_motu_packet_format *formats,
+6 −6
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ static void motu_bus_update(struct fw_unit *unit)
	snd_motu_transaction_reregister(motu);
}

static const struct snd_motu_spec motu_828mk2 = {
const struct snd_motu_spec snd_motu_spec_828mk2 = {
	.name = "828mk2",
	.protocol = &snd_motu_protocol_v2,
	.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
@@ -187,7 +187,7 @@ static const struct snd_motu_spec motu_828mk2 = {
	.analog_out_ports = 8,
};

const struct snd_motu_spec snd_motu_spec_traveler = {
static const struct snd_motu_spec motu_traveler = {
	.name = "Traveler",
	.protocol = &snd_motu_protocol_v2,
	.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
@@ -202,7 +202,7 @@ const struct snd_motu_spec snd_motu_spec_traveler = {
	.analog_out_ports = 8,
};

const struct snd_motu_spec snd_motu_spec_8pre = {
static const struct snd_motu_spec motu_8pre = {
	.name = "8pre",
	.protocol = &snd_motu_protocol_v2,
	// In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for
@@ -270,9 +270,9 @@ static const struct snd_motu_spec motu_4pre = {
}

static const struct ieee1394_device_id motu_id_table[] = {
	SND_MOTU_DEV_ENTRY(0x000003, &motu_828mk2),
	SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
	SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
	SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2),
	SND_MOTU_DEV_ENTRY(0x000009, &motu_traveler),
	SND_MOTU_DEV_ENTRY(0x00000f, &motu_8pre),
	SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3),	/* FireWire only. */
	SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3),	/* Hybrid. */
	SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express),
+1 −2
Original line number Diff line number Diff line
@@ -130,8 +130,7 @@ struct snd_motu_spec {
extern const struct snd_motu_protocol snd_motu_protocol_v2;
extern const struct snd_motu_protocol snd_motu_protocol_v3;

extern const struct snd_motu_spec snd_motu_spec_traveler;
extern const struct snd_motu_spec snd_motu_spec_8pre;
extern const struct snd_motu_spec snd_motu_spec_828mk2;

int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
		    enum amdtp_stream_direction dir,