Skip to content

Commit

Permalink
ALSA: fireface: support allocate_resources operation in latter protocol
Browse files Browse the repository at this point in the history
This commit is a part of preparation to perform allocation/release
of isochronous channels in pcm.hw_params/hw_free callbacks.

This commit implements allocate_resources callback for the protocol
specific to latter models. The encoded values of constant table is
split into several condition statements to separate the operation
to configure sampling transfer frequency from the operation to
configure the number of data channels in rx packet.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
takaswie authored and tiwai committed Jun 11, 2019
1 parent 75be43d commit 60aec49
Showing 1 changed file with 56 additions and 57 deletions.
113 changes: 56 additions & 57 deletions sound/firewire/fireface/ff-protocol-latter.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,33 +97,72 @@ static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable)
LATTER_FETCH_MODE, &reg, sizeof(reg), 0);
}

static int keep_resources(struct snd_ff *ff, unsigned int rate)
static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate)
{
enum snd_ff_stream_mode mode;
unsigned int code;
__le32 reg;
unsigned int count;
int i;
int err;

// Check whether the given value is supported or not.
for (i = 0; i < CIP_SFC_COUNT; i++) {
if (amdtp_rate_table[i] == rate)
// Set the number of data blocks transferred in a second.
if (rate % 32000 == 0)
code = 0x00;
else if (rate % 44100 == 0)
code = 0x02;
else if (rate % 48000 == 0)
code = 0x04;
else
return -EINVAL;

if (rate >= 64000 && rate < 128000)
code |= 0x08;
else if (rate >= 128000 && rate < 192000)
code |= 0x10;

reg = cpu_to_le32(code);
err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
LATTER_STF, &reg, sizeof(reg), 0);
if (err < 0)
return err;

// Confirm to shift transmission clock.
count = 0;
while (count++ < 10) {
unsigned int curr_rate;
enum snd_ff_clock_src src;

err = latter_get_clock(ff, &curr_rate, &src);
if (err < 0)
return err;

if (curr_rate == rate)
break;
}
if (i >= CIP_SFC_COUNT)
if (count == 10)
return -ETIMEDOUT;

for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); ++i) {
if (rate == amdtp_rate_table[i])
break;
}
if (i == ARRAY_SIZE(amdtp_rate_table))
return -EINVAL;

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

/* Keep resources for in-stream. */
// Keep resources for in-stream.
ff->tx_resources.channels_mask = 0x00000000000000ffuLL;
err = fw_iso_resources_allocate(&ff->tx_resources,
amdtp_stream_get_max_payload(&ff->tx_stream),
fw_parent_device(ff->unit)->max_speed);
if (err < 0)
return err;

/* Keep resources for out-stream. */
// Keep resources for out-stream.
ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
err = fw_iso_resources_allocate(&ff->rx_resources,
amdtp_stream_get_max_payload(&ff->rx_stream),
Expand All @@ -136,61 +175,20 @@ static int keep_resources(struct snd_ff *ff, unsigned int rate)

static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
{
static const struct {
unsigned int stf;
unsigned int code;
unsigned int flag;
} *entry, rate_table[] = {
{ 32000, 0x00, 0x92, },
{ 44100, 0x02, 0x92, },
{ 48000, 0x04, 0x92, },
{ 64000, 0x08, 0x8e, },
{ 88200, 0x0a, 0x8e, },
{ 96000, 0x0c, 0x8e, },
{ 128000, 0x10, 0x8c, },
{ 176400, 0x12, 0x8c, },
{ 192000, 0x14, 0x8c, },
};
unsigned int flag;
u32 data;
__le32 reg;
unsigned int count;
int i;
int err;

for (i = 0; i < ARRAY_SIZE(rate_table); ++i) {
entry = rate_table + i;
if (entry->stf == rate)
break;
}
if (i == ARRAY_SIZE(rate_table))
if (rate >= 32000 && rate <= 48000)
flag = 0x92;
else if (rate >= 64000 && rate <= 96000)
flag = 0x8e;
else if (rate >= 128000 && rate <= 192000)
flag = 0x8c;
else
return -EINVAL;

reg = cpu_to_le32(entry->code);
err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
LATTER_STF, &reg, sizeof(reg), 0);
if (err < 0)
return err;

// Confirm to shift transmission clock.
count = 0;
while (count++ < 10) {
unsigned int curr_rate;
enum snd_ff_clock_src src;

err = latter_get_clock(ff, &curr_rate, &src);
if (err < 0)
return err;

if (curr_rate == rate)
break;
}
if (count == 10)
return -ETIMEDOUT;

err = keep_resources(ff, rate);
if (err < 0)
return err;

data = (ff->tx_resources.channel << 8) | ff->rx_resources.channel;
reg = cpu_to_le32(data);
err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
Expand All @@ -200,7 +198,7 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate)

// Always use the maximum number of data channels in data block of
// packet.
reg = cpu_to_le32(entry->flag);
reg = cpu_to_le32(flag);
return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
LATTER_ISOC_START, &reg, sizeof(reg), 0);
}
Expand Down Expand Up @@ -424,6 +422,7 @@ const struct snd_ff_protocol snd_ff_protocol_latter = {
.fill_midi_msg = latter_fill_midi_msg,
.get_clock = latter_get_clock,
.switch_fetching_mode = latter_switch_fetching_mode,
.allocate_resources = latter_allocate_resources,
.begin_session = latter_begin_session,
.finish_session = latter_finish_session,
.dump_status = latter_dump_status,
Expand Down

0 comments on commit 60aec49

Please sign in to comment.