ALSA: fireface: support allocate_resources operation in latter protocol
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>
This commit is contained in:
parent
75be43d97f
commit
60aec494b3
@ -97,75 +97,31 @@ static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable)
|
||||
LATTER_FETCH_MODE, ®, 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;
|
||||
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)
|
||||
break;
|
||||
}
|
||||
if (i >= CIP_SFC_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
err = snd_ff_stream_get_multiplier_mode(i, &mode);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* 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. */
|
||||
ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
|
||||
err = fw_iso_resources_allocate(&ff->rx_resources,
|
||||
amdtp_stream_get_max_payload(&ff->rx_stream),
|
||||
fw_parent_device(ff->unit)->max_speed);
|
||||
if (err < 0)
|
||||
fw_iso_resources_free(&ff->tx_resources);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
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, },
|
||||
};
|
||||
u32 data;
|
||||
unsigned int code;
|
||||
__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))
|
||||
// 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;
|
||||
|
||||
reg = cpu_to_le32(entry->code);
|
||||
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, ®, sizeof(reg), 0);
|
||||
if (err < 0)
|
||||
@ -187,10 +143,52 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
|
||||
if (count == 10)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
err = keep_resources(ff, rate);
|
||||
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.
|
||||
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.
|
||||
ff->rx_resources.channels_mask = 0x00000000000000ffuLL;
|
||||
err = fw_iso_resources_allocate(&ff->rx_resources,
|
||||
amdtp_stream_get_max_payload(&ff->rx_stream),
|
||||
fw_parent_device(ff->unit)->max_speed);
|
||||
if (err < 0)
|
||||
fw_iso_resources_free(&ff->tx_resources);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
|
||||
{
|
||||
unsigned int flag;
|
||||
u32 data;
|
||||
__le32 reg;
|
||||
int err;
|
||||
|
||||
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;
|
||||
|
||||
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,
|
||||
@ -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, ®, sizeof(reg), 0);
|
||||
}
|
||||
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user