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

ALSA: fireface: code refactoring to handle multiplier mode



Fireface 400/800 use three modes against the number of data channels in
data block for both tx/rx packets.

This commit adds refactoring for it. Some enumerators are added to
represent each of mode and a function is added to calculate the mode
from sampling frequency code (sfc).

Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent d4a0b6cb
Loading
Loading
Loading
Loading
+22 −11
Original line number Diff line number Diff line
@@ -8,11 +8,6 @@

#include "ff.h"

static inline unsigned int get_multiplier_mode_with_index(unsigned int index)
{
	return ((int)index - 1) / 2;
}

static int hw_rule_rate(struct snd_pcm_hw_params *params,
			struct snd_pcm_hw_rule *rule)
{
@@ -24,10 +19,16 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
	struct snd_interval t = {
		.min = UINT_MAX, .max = 0, .integer = 1
	};
	unsigned int i, mode;
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
		mode = get_multiplier_mode_with_index(i);
		enum snd_ff_stream_mode mode;
		int err;

		err = snd_ff_stream_get_multiplier_mode(i, &mode);
		if (err < 0)
			continue;

		if (!snd_interval_test(c, pcm_channels[mode]))
			continue;

@@ -49,10 +50,16 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
	struct snd_interval t = {
		.min = UINT_MAX, .max = 0, .integer = 1
	};
	unsigned int i, mode;
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
		mode = get_multiplier_mode_with_index(i);
		enum snd_ff_stream_mode mode;
		int err;

		err = snd_ff_stream_get_multiplier_mode(i, &mode);
		if (err < 0)
			continue;

		if (!snd_interval_test(r, amdtp_rate_table[i]))
			continue;

@@ -66,7 +73,6 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
static void limit_channels_and_rates(struct snd_pcm_hardware *hw,
				     const unsigned int *pcm_channels)
{
	unsigned int mode;
	unsigned int rate, channels;
	int i;

@@ -76,7 +82,12 @@ static void limit_channels_and_rates(struct snd_pcm_hardware *hw,
	hw->rate_max = 0;

	for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
		mode = get_multiplier_mode_with_index(i);
		enum snd_ff_stream_mode mode;
		int err;

		err = snd_ff_stream_get_multiplier_mode(i, &mode);
		if (err < 0)
			continue;

		channels = pcm_channels[mode];
		if (pcm_channels[mode] == 0)
+25 −13
Original line number Diff line number Diff line
@@ -10,19 +10,23 @@

#define CALLBACK_TIMEOUT_MS	200

static int get_rate_mode(unsigned int rate, unsigned int *mode)
int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
				      enum snd_ff_stream_mode *mode)
{
	int i;

	for (i = 0; i < CIP_SFC_COUNT; i++) {
		if (amdtp_rate_table[i] == rate)
			break;
	}

	if (i == CIP_SFC_COUNT)
	static const enum snd_ff_stream_mode modes[] = {
		[CIP_SFC_32000] = SND_FF_STREAM_MODE_LOW,
		[CIP_SFC_44100] = SND_FF_STREAM_MODE_LOW,
		[CIP_SFC_48000] = SND_FF_STREAM_MODE_LOW,
		[CIP_SFC_88200] = SND_FF_STREAM_MODE_MID,
		[CIP_SFC_96000] = SND_FF_STREAM_MODE_MID,
		[CIP_SFC_176400] = SND_FF_STREAM_MODE_HIGH,
		[CIP_SFC_192000] = SND_FF_STREAM_MODE_HIGH,
	};

	if (sfc >= CIP_SFC_COUNT)
		return -EINVAL;

	*mode = ((int)i - 1) / 2;
	*mode = modes[sfc];

	return 0;
}
@@ -33,10 +37,18 @@ static int get_rate_mode(unsigned int rate, unsigned int *mode)
 */
static int keep_resources(struct snd_ff *ff, unsigned int rate)
{
	int mode;
	enum snd_ff_stream_mode mode;
	int i;
	int err;

	err = get_rate_mode(rate, &mode);
	for (i = 0; i < CIP_SFC_COUNT; ++i) {
		if (amdtp_rate_table[i] == rate)
			break;
	}
	if (i == CIP_SFC_COUNT)
		return -EINVAL;

	err = snd_ff_stream_get_multiplier_mode(i, &mode);
	if (err < 0)
		return err;

@@ -81,7 +93,7 @@ static int switch_fetching_mode(struct snd_ff *ff, bool enable)
	int err;

	count = 0;
	for (i = 0; i < SND_FF_STREAM_MODES; ++i)
	for (i = 0; i < SND_FF_STREAM_MODE_COUNT; ++i)
		count = max(count, ff->spec->pcm_playback_channels[i]);

	reg = kcalloc(count, sizeof(__le32), GFP_KERNEL);
+11 −4
Original line number Diff line number Diff line
@@ -31,8 +31,6 @@
#include "../amdtp-stream.h"
#include "../iso-resources.h"

#define SND_FF_STREAM_MODES		3

#define SND_FF_MAXIMIM_MIDI_QUADS	9
#define SND_FF_IN_MIDI_PORTS		2
#define SND_FF_OUT_MIDI_PORTS		2
@@ -42,6 +40,13 @@
#define SND_FF_REG_FETCH_PCM_FRAMES	0x0000801c0000ull
#define SND_FF_REG_CLOCK_CONFIG		0x0000801c0004ull

enum snd_ff_stream_mode {
	SND_FF_STREAM_MODE_LOW = 0,
	SND_FF_STREAM_MODE_MID,
	SND_FF_STREAM_MODE_HIGH,
	SND_FF_STREAM_MODE_COUNT,
};

enum snd_ff_reg_type {
	SND_FF_REG_TYPE_MIDI_HIGH_ADDR = 0,
	SND_FF_REG_TYPE_COUNT,
@@ -51,8 +56,8 @@ struct snd_ff_protocol;
struct snd_ff_spec {
	const char *const name;

	const unsigned int pcm_capture_channels[SND_FF_STREAM_MODES];
	const unsigned int pcm_playback_channels[SND_FF_STREAM_MODES];
	const unsigned int pcm_capture_channels[SND_FF_STREAM_MODE_COUNT];
	const unsigned int pcm_playback_channels[SND_FF_STREAM_MODE_COUNT];

	unsigned int midi_in_ports;
	unsigned int midi_out_ports;
@@ -129,6 +134,8 @@ int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s,
int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit,
		  enum amdtp_stream_direction dir);

int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
				      enum snd_ff_stream_mode *mode);
int snd_ff_stream_init_duplex(struct snd_ff *ff);
void snd_ff_stream_destroy_duplex(struct snd_ff *ff);
int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate);