* [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks
@ 2019-06-02 7:12 Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 01/15] ALSA: firewire-tascam: code refactoring for registration of isochronous channels Takashi Sakamoto
` (15 more replies)
0 siblings, 16 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
Hi,
This patchset is a part of series of patches for all of drivers in
ALSA firewire stack to reserve/release isochronous resources in
pcm.hw_params/hw_free callbacks.
In current implementation, the resources are reserved at the same time
to start packet streaming, and released at the same time to stop packet
streaming. However, once allocated, the resources are available
independent of lifetime of packet streaming.
The isochronous resources are the resources of IEEE 1394 bus. On the
other side of view, it's a kind of resources of hardware to maintain
the bus (isochronous resource manager). For this kind of reservation and
release, hw_params and hw_free operations are suitable in ALSA PCM
interface.
Ideally, the operation to reserve/release isochronous resource should
be separated from the operation to start/stop packet streaming. However,
IEEE 1394 bus has reset event. Once reset occurs, isochronous resource
manager releases allocated resources. The resources should be
reallocated by requesters themselves. For this reason, in this patchset,
bus generation is checked before starting packet streaming. If
generation is updated, reallocation is requested to isochronous
resource manager, then packet streaming starts.
Takashi Sakamoto (15):
ALSA: firewire-tascam: code refactoring for registration of
isochronous channels
ALSA: firewire-tascam: code refactoring for reservation of isochronous
resources
ALSA: firewire-tascam: code refactoring for release of isochronous
resources
ALSA: firewire-tascam: reserve/release isochronous resources in
pcm.hw_params/hw_free callbacks
ALSA: firewire-tascam: update isochronous resources when starting
packet streaming after bus reset
ALSA: firewire-tascam: minor code refactoring to finish streaming
session
ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free
callbacks
ALSA: fireface: add protocol-specific operation to allocate
isochronous resources
ALSA: fireface: support allocate_resources operation in ff800 protocol
ALSA: fireface: support allocate_resources operation in ff400 protocol
ALSA: fireface: support allocate_resources operation in latter
protocol
ALSA: fireface: reserve/release isochronous resources in
pcm.hw_params/hw_free callbacks
ALSA: fireface: update isochronous resources when starting packet
streaming after bus-reset
ALSA: fireface: minor code refactoring to finish streaming session
ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks
sound/firewire/fireface/ff-pcm.c | 57 ++---
sound/firewire/fireface/ff-protocol-former.c | 112 +++++-----
sound/firewire/fireface/ff-protocol-latter.c | 114 +++++-----
sound/firewire/fireface/ff-stream.c | 85 ++++----
sound/firewire/fireface/ff.h | 3 +
sound/firewire/tascam/tascam-pcm.c | 59 ++----
sound/firewire/tascam/tascam-stream.c | 209 ++++++++++---------
sound/firewire/tascam/tascam.h | 2 +
8 files changed, 306 insertions(+), 335 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 01/15] ALSA: firewire-tascam: code refactoring for registration of isochronous channels
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 02/15] ALSA: firewire-tascam: code refactoring for reservation of isochronous resources Takashi Sakamoto
` (14 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
This commit is a part of preparation to perform allocation/release
of isochronous channels in pcm.hw_params/hw_free callbacks.
The registration of isochronous channels is done just after allocation
of isochronous resources. This commit separates the registration just
before starting packet streaming.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/tascam/tascam-stream.c | 84 +++++++++++++--------------
1 file changed, 40 insertions(+), 44 deletions(-)
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index f1657a4e0621..7cddd9ece4ee 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -195,6 +195,19 @@ static void finish_session(struct snd_tscm *tscm)
TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_ON,
®, sizeof(reg), 0);
+ // Unregister channels.
+ reg = cpu_to_be32(0x00000000);
+ snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
+ TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
+ ®, sizeof(reg), 0);
+ reg = cpu_to_be32(0x00000000);
+ snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
+ TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
+ ®, sizeof(reg), 0);
+ reg = cpu_to_be32(0x00000000);
+ snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
+ TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
+ ®, sizeof(reg), 0);
}
static int begin_session(struct snd_tscm *tscm)
@@ -202,6 +215,30 @@ static int begin_session(struct snd_tscm *tscm)
__be32 reg;
int err;
+ // Register the isochronous channel for transmitting stream.
+ reg = cpu_to_be32(tscm->tx_resources.channel);
+ err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
+ TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
+ ®, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ // Unknown.
+ reg = cpu_to_be32(0x00000002);
+ err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
+ TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
+ ®, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ // Register the isochronous channel for receiving stream.
+ reg = cpu_to_be32(tscm->rx_resources.channel);
+ err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
+ TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
+ ®, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
reg = cpu_to_be32(0x00000001);
err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
@@ -216,7 +253,7 @@ static int begin_session(struct snd_tscm *tscm)
if (err < 0)
return err;
- /* Set an option for unknown purpose. */
+ // Set an option for unknown purpose.
reg = cpu_to_be32(0x00002000);
err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
@@ -224,7 +261,7 @@ static int begin_session(struct snd_tscm *tscm)
if (err < 0)
return err;
- /* Start multiplexing PCM samples on packets. */
+ // Start multiplexing PCM samples on packets.
reg = cpu_to_be32(0x00000001);
return snd_fw_transaction(tscm->unit,
TCODE_WRITE_QUADLET_REQUEST,
@@ -234,30 +271,13 @@ static int begin_session(struct snd_tscm *tscm)
static void release_resources(struct snd_tscm *tscm)
{
- __be32 reg;
-
- /* Unregister channels. */
- reg = cpu_to_be32(0x00000000);
- snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
- TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
- ®, sizeof(reg), 0);
- reg = cpu_to_be32(0x00000000);
- snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
- TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
- ®, sizeof(reg), 0);
- reg = cpu_to_be32(0x00000000);
- snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
- TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
- ®, sizeof(reg), 0);
-
- /* Release isochronous resources. */
+ // Release isochronous resources.
fw_iso_resources_free(&tscm->tx_resources);
fw_iso_resources_free(&tscm->rx_resources);
}
static int keep_resources(struct snd_tscm *tscm, unsigned int rate)
{
- __be32 reg;
int err;
/* Keep resources for in-stream. */
@@ -280,30 +300,6 @@ static int keep_resources(struct snd_tscm *tscm, unsigned int rate)
if (err < 0)
return err;
- /* Register the isochronous channel for transmitting stream. */
- reg = cpu_to_be32(tscm->tx_resources.channel);
- err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
- TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_TX_CH,
- ®, sizeof(reg), 0);
- if (err < 0)
- goto error;
-
- /* Unknown */
- reg = cpu_to_be32(0x00000002);
- err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
- TSCM_ADDR_BASE + TSCM_OFFSET_UNKNOWN,
- ®, sizeof(reg), 0);
- if (err < 0)
- goto error;
-
- /* Register the isochronous channel for receiving stream. */
- reg = cpu_to_be32(tscm->rx_resources.channel);
- err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
- TSCM_ADDR_BASE + TSCM_OFFSET_ISOC_RX_CH,
- ®, sizeof(reg), 0);
- if (err < 0)
- goto error;
-
return 0;
error:
release_resources(tscm);
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 02/15] ALSA: firewire-tascam: code refactoring for reservation of isochronous resources
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 01/15] ALSA: firewire-tascam: code refactoring for registration of isochronous channels Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 03/15] ALSA: firewire-tascam: code refactoring for release " Takashi Sakamoto
` (13 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
This commit is a part of preparation to perform allocation/release
of isochronous channels in pcm.hw_params/hw_free callbacks.
This commit applies minor code refactoring for a helper function to
allocate isochronous resources.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/tascam/tascam-stream.c | 38 +++++++++++----------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index 7cddd9ece4ee..fc963469f6b0 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -276,34 +276,24 @@ static void release_resources(struct snd_tscm *tscm)
fw_iso_resources_free(&tscm->rx_resources);
}
-static int keep_resources(struct snd_tscm *tscm, unsigned int rate)
+static int keep_resources(struct snd_tscm *tscm, unsigned int rate,
+ struct amdtp_stream *stream)
{
+ struct fw_iso_resources *resources;
int err;
- /* Keep resources for in-stream. */
- err = amdtp_tscm_set_parameters(&tscm->tx_stream, rate);
- if (err < 0)
- return err;
- err = fw_iso_resources_allocate(&tscm->tx_resources,
- amdtp_stream_get_max_payload(&tscm->tx_stream),
- fw_parent_device(tscm->unit)->max_speed);
- if (err < 0)
- goto error;
+ if (stream == &tscm->tx_stream)
+ resources = &tscm->tx_resources;
+ else
+ resources = &tscm->rx_resources;
- /* Keep resources for out-stream. */
- err = amdtp_tscm_set_parameters(&tscm->rx_stream, rate);
- if (err < 0)
- return err;
- err = fw_iso_resources_allocate(&tscm->rx_resources,
- amdtp_stream_get_max_payload(&tscm->rx_stream),
- fw_parent_device(tscm->unit)->max_speed);
+ err = amdtp_tscm_set_parameters(stream, rate);
if (err < 0)
return err;
- return 0;
-error:
- release_resources(tscm);
- return err;
+ return fw_iso_resources_allocate(resources,
+ amdtp_stream_get_max_payload(stream),
+ fw_parent_device(tscm->unit)->max_speed);
}
int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
@@ -388,7 +378,11 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
}
if (!amdtp_stream_running(&tscm->rx_stream)) {
- err = keep_resources(tscm, rate);
+ err = keep_resources(tscm, rate, &tscm->tx_stream);
+ if (err < 0)
+ goto error;
+
+ err = keep_resources(tscm, rate, &tscm->rx_stream);
if (err < 0)
goto error;
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 03/15] ALSA: firewire-tascam: code refactoring for release of isochronous resources
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 01/15] ALSA: firewire-tascam: code refactoring for registration of isochronous channels Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 02/15] ALSA: firewire-tascam: code refactoring for reservation of isochronous resources Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 04/15] ALSA: firewire-tascam: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (12 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
This commit is a part of preparation to perform allocation/release
of isochronous channels in pcm.hw_params/hw_free callbacks.
This commit obsoletes a helper function to release isochronous resources
for both direction.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/tascam/tascam-stream.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index fc963469f6b0..6ad149274050 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -269,13 +269,6 @@ static int begin_session(struct snd_tscm *tscm)
®, sizeof(reg), 0);
}
-static void release_resources(struct snd_tscm *tscm)
-{
- // Release isochronous resources.
- fw_iso_resources_free(&tscm->tx_resources);
- fw_iso_resources_free(&tscm->rx_resources);
-}
-
static int keep_resources(struct snd_tscm *tscm, unsigned int rate,
struct amdtp_stream *stream)
{
@@ -374,7 +367,8 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
amdtp_stream_stop(&tscm->rx_stream);
amdtp_stream_stop(&tscm->tx_stream);
- release_resources(tscm);
+ fw_iso_resources_free(&tscm->tx_resources);
+ fw_iso_resources_free(&tscm->rx_resources);
}
if (!amdtp_stream_running(&tscm->rx_stream)) {
@@ -427,7 +421,9 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
amdtp_stream_stop(&tscm->tx_stream);
finish_session(tscm);
- release_resources(tscm);
+
+ fw_iso_resources_free(&tscm->tx_resources);
+ fw_iso_resources_free(&tscm->rx_resources);
return err;
}
@@ -441,7 +437,9 @@ void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
amdtp_stream_stop(&tscm->rx_stream);
finish_session(tscm);
- release_resources(tscm);
+
+ fw_iso_resources_free(&tscm->tx_resources);
+ fw_iso_resources_free(&tscm->rx_resources);
}
void snd_tscm_stream_lock_changed(struct snd_tscm *tscm)
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 04/15] ALSA: firewire-tascam: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (2 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 03/15] ALSA: firewire-tascam: code refactoring for release " Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 05/15] ALSA: firewire-tascam: update isochronous resources when starting packet streaming after bus reset Takashi Sakamoto
` (11 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
Once allocated, isochronous resources are available for packet
streaming, even if the streaming is cancelled. For this reason,
current implementation handles allocation of the resources and
starting packet streaming at the same time. However, this brings
complicated procedure to start packet streaming.
This commit separates the allocation and starting. The allocation is
done in pcm.hw_params callback and available till pcm.hw_free callback.
Even if any XRUN occurs, pcm.prepare callback is done to restart
packet streaming for allocated the resources.
There are two points to stop packet streaming; in pcm.hw_params and
pcm.prepare callbacks.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/tascam/tascam-pcm.c | 22 ++++++--
sound/firewire/tascam/tascam-stream.c | 79 ++++++++++++++++-----------
sound/firewire/tascam/tascam.h | 2 +
3 files changed, 66 insertions(+), 37 deletions(-)
diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c
index e4cc8990e195..962ef1212ac0 100644
--- a/sound/firewire/tascam/tascam-pcm.c
+++ b/sound/firewire/tascam/tascam-pcm.c
@@ -96,12 +96,16 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
return err;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ unsigned int rate = params_rate(hw_params);
+
mutex_lock(&tscm->mutex);
- tscm->substreams_counter++;
+ err = snd_tscm_stream_reserve_duplex(tscm, rate);
+ if (err >= 0)
+ ++tscm->substreams_counter;
mutex_unlock(&tscm->mutex);
}
- return 0;
+ return err;
}
static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
@@ -116,12 +120,16 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
return err;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ unsigned int rate = params_rate(hw_params);
+
mutex_lock(&tscm->mutex);
- tscm->substreams_counter++;
+ err = snd_tscm_stream_reserve_duplex(tscm, rate);
+ if (err >= 0)
+ ++tscm->substreams_counter;
mutex_unlock(&tscm->mutex);
}
- return 0;
+ return err;
}
static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
@@ -131,9 +139,10 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&tscm->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- tscm->substreams_counter--;
+ --tscm->substreams_counter;
snd_tscm_stream_stop_duplex(tscm);
+ snd_tscm_stream_release_duplex(tscm);
mutex_unlock(&tscm->mutex);
@@ -147,9 +156,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&tscm->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- tscm->substreams_counter--;
+ --tscm->substreams_counter;
snd_tscm_stream_stop_duplex(tscm);
+ snd_tscm_stream_release_duplex(tscm);
mutex_unlock(&tscm->mutex);
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index 6ad149274050..18d554d46be5 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -166,7 +166,7 @@ static int set_stream_formats(struct snd_tscm *tscm, unsigned int rate)
__be32 reg;
int err;
- /* Set an option for unknown purpose. */
+ // Set an option for unknown purpose.
reg = cpu_to_be32(0x00200000);
err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
TSCM_ADDR_BASE + TSCM_OFFSET_SET_OPTION,
@@ -174,11 +174,7 @@ static int set_stream_formats(struct snd_tscm *tscm, unsigned int rate)
if (err < 0)
return err;
- err = enable_data_channels(tscm);
- if (err < 0)
- return err;
-
- return set_clock(tscm, rate, INT_MAX);
+ return enable_data_channels(tscm);
}
static void finish_session(struct snd_tscm *tscm)
@@ -348,38 +344,66 @@ void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm)
fw_iso_resources_destroy(&tscm->tx_resources);
}
-int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
+int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate)
{
unsigned int curr_rate;
int err;
- if (tscm->substreams_counter == 0)
- return 0;
-
err = snd_tscm_stream_get_rate(tscm, &curr_rate);
if (err < 0)
return err;
- if (curr_rate != rate ||
- amdtp_streaming_error(&tscm->rx_stream) ||
- amdtp_streaming_error(&tscm->tx_stream)) {
- finish_session(tscm);
+ if (tscm->substreams_counter == 0 || rate != curr_rate) {
amdtp_stream_stop(&tscm->rx_stream);
amdtp_stream_stop(&tscm->tx_stream);
+ finish_session(tscm);
+
fw_iso_resources_free(&tscm->tx_resources);
fw_iso_resources_free(&tscm->rx_resources);
- }
- if (!amdtp_stream_running(&tscm->rx_stream)) {
+ err = set_clock(tscm, rate, INT_MAX);
+ if (err < 0)
+ return err;
+
err = keep_resources(tscm, rate, &tscm->tx_stream);
if (err < 0)
- goto error;
+ return err;
err = keep_resources(tscm, rate, &tscm->rx_stream);
- if (err < 0)
- goto error;
+ if (err < 0) {
+ fw_iso_resources_free(&tscm->tx_resources);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+void snd_tscm_stream_release_duplex(struct snd_tscm *tscm)
+{
+ if (tscm->substreams_counter == 0) {
+ fw_iso_resources_free(&tscm->tx_resources);
+ fw_iso_resources_free(&tscm->rx_resources);
+ }
+}
+
+int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
+{
+ int err;
+
+ if (tscm->substreams_counter == 0)
+ return 0;
+
+ if (amdtp_streaming_error(&tscm->rx_stream) ||
+ amdtp_streaming_error(&tscm->tx_stream)) {
+ amdtp_stream_stop(&tscm->rx_stream);
+ amdtp_stream_stop(&tscm->tx_stream);
+ finish_session(tscm);
+ }
+
+ if (!amdtp_stream_running(&tscm->rx_stream)) {
err = set_stream_formats(tscm, rate);
if (err < 0)
goto error;
@@ -422,24 +446,17 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
finish_session(tscm);
- fw_iso_resources_free(&tscm->tx_resources);
- fw_iso_resources_free(&tscm->rx_resources);
-
return err;
}
void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
{
- if (tscm->substreams_counter > 0)
- return;
-
- amdtp_stream_stop(&tscm->tx_stream);
- amdtp_stream_stop(&tscm->rx_stream);
-
- finish_session(tscm);
+ if (tscm->substreams_counter == 0) {
+ amdtp_stream_stop(&tscm->tx_stream);
+ amdtp_stream_stop(&tscm->rx_stream);
- fw_iso_resources_free(&tscm->tx_resources);
- fw_iso_resources_free(&tscm->rx_resources);
+ finish_session(tscm);
+ }
}
void snd_tscm_stream_lock_changed(struct snd_tscm *tscm)
diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h
index 6a411ee0dcf1..1cb75c374f11 100644
--- a/sound/firewire/tascam/tascam.h
+++ b/sound/firewire/tascam/tascam.h
@@ -147,6 +147,8 @@ int snd_tscm_stream_get_clock(struct snd_tscm *tscm,
int snd_tscm_stream_init_duplex(struct snd_tscm *tscm);
void snd_tscm_stream_update_duplex(struct snd_tscm *tscm);
void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm);
+int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate);
+void snd_tscm_stream_release_duplex(struct snd_tscm *tscm);
int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate);
void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm);
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 05/15] ALSA: firewire-tascam: update isochronous resources when starting packet streaming after bus reset
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (3 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 04/15] ALSA: firewire-tascam: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 06/15] ALSA: firewire-tascam: minor code refactoring to finish streaming session Takashi Sakamoto
` (10 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
After bus reset, isochronous resource manager releases all of allocated
isochronous resources. The nodes to restart packet streaming should
request reallocation of the resources.
However, between the bus-reset and invocation of 'struct fw_driver.update'
handler, ALSA PCM application can detect this situation by XRUN because
the target device cancelled to transmit packets once bus-reset occurs.
Due to the above mechanism, ALSA firewire-tascam driver just stops
packet streaming in the update handler, thus pcm.prepare handler
should request the reallocation.
This commit requests the reallocation in pcm.prepare callback when
bus generation is changed.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/tascam/tascam-stream.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index 18d554d46be5..be9dcc808188 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -321,7 +321,7 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
return err;
}
-/* At bus reset, streaming is stopped and some registers are clear. */
+// At bus reset, streaming is stopped and some registers are clear.
void snd_tscm_stream_update_duplex(struct snd_tscm *tscm)
{
amdtp_stream_pcm_abort(&tscm->tx_stream);
@@ -390,6 +390,7 @@ void snd_tscm_stream_release_duplex(struct snd_tscm *tscm)
int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
{
+ unsigned int generation = tscm->rx_resources.generation;
int err;
if (tscm->substreams_counter == 0)
@@ -403,6 +404,16 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
finish_session(tscm);
}
+ if (generation != fw_parent_device(tscm->unit)->card->generation) {
+ err = fw_iso_resources_update(&tscm->tx_resources);
+ if (err < 0)
+ goto error;
+
+ err = fw_iso_resources_update(&tscm->rx_resources);
+ if (err < 0)
+ goto error;
+ }
+
if (!amdtp_stream_running(&tscm->rx_stream)) {
err = set_stream_formats(tscm, rate);
if (err < 0)
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 06/15] ALSA: firewire-tascam: minor code refactoring to finish streaming session
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (4 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 05/15] ALSA: firewire-tascam: update isochronous resources when starting packet streaming after bus reset Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 07/15] ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (9 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
The operation to finish packet streaming corresponds to stopping
isochronous contexts.
This commit applies code refactoring to move codes to stop into
a helper function to finish the session.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/tascam/tascam-stream.c | 21 +++++----------------
1 file changed, 5 insertions(+), 16 deletions(-)
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index be9dcc808188..f572dfc15114 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -181,6 +181,9 @@ static void finish_session(struct snd_tscm *tscm)
{
__be32 reg;
+ amdtp_stream_stop(&tscm->rx_stream);
+ amdtp_stream_stop(&tscm->tx_stream);
+
reg = 0;
snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING,
@@ -354,9 +357,6 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate)
return err;
if (tscm->substreams_counter == 0 || rate != curr_rate) {
- amdtp_stream_stop(&tscm->rx_stream);
- amdtp_stream_stop(&tscm->tx_stream);
-
finish_session(tscm);
fw_iso_resources_free(&tscm->tx_resources);
@@ -397,12 +397,8 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
return 0;
if (amdtp_streaming_error(&tscm->rx_stream) ||
- amdtp_streaming_error(&tscm->tx_stream)) {
- amdtp_stream_stop(&tscm->rx_stream);
- amdtp_stream_stop(&tscm->tx_stream);
-
+ amdtp_streaming_error(&tscm->tx_stream))
finish_session(tscm);
- }
if (generation != fw_parent_device(tscm->unit)->card->generation) {
err = fw_iso_resources_update(&tscm->tx_resources);
@@ -452,9 +448,6 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
return 0;
error:
- amdtp_stream_stop(&tscm->rx_stream);
- amdtp_stream_stop(&tscm->tx_stream);
-
finish_session(tscm);
return err;
@@ -462,12 +455,8 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm)
{
- if (tscm->substreams_counter == 0) {
- amdtp_stream_stop(&tscm->tx_stream);
- amdtp_stream_stop(&tscm->rx_stream);
-
+ if (tscm->substreams_counter == 0)
finish_session(tscm);
- }
}
void snd_tscm_stream_lock_changed(struct snd_tscm *tscm)
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 07/15] ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free callbacks
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (5 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 06/15] ALSA: firewire-tascam: minor code refactoring to finish streaming session Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 08/15] ALSA: fireface: add protocol-specific operation to allocate isochronous resources Takashi Sakamoto
` (8 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
The pairs of pcm.hw_params callbacks and .hw_free callbacks for both
direction have no differences.
This commit unifies the pairs.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/tascam/tascam-pcm.c | 55 ++++--------------------------
1 file changed, 7 insertions(+), 48 deletions(-)
diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c
index 962ef1212ac0..450711bef508 100644
--- a/sound/firewire/tascam/tascam-pcm.c
+++ b/sound/firewire/tascam/tascam-pcm.c
@@ -84,8 +84,8 @@ static int pcm_close(struct snd_pcm_substream *substream)
return 0;
}
-static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
+static int pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
struct snd_tscm *tscm = substream->private_data;
int err;
@@ -108,48 +108,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
return err;
}
-static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_tscm *tscm = substream->private_data;
- int err;
-
- err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
- params_buffer_bytes(hw_params));
- if (err < 0)
- return err;
-
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- unsigned int rate = params_rate(hw_params);
-
- mutex_lock(&tscm->mutex);
- err = snd_tscm_stream_reserve_duplex(tscm, rate);
- if (err >= 0)
- ++tscm->substreams_counter;
- mutex_unlock(&tscm->mutex);
- }
-
- return err;
-}
-
-static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_tscm *tscm = substream->private_data;
-
- mutex_lock(&tscm->mutex);
-
- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- --tscm->substreams_counter;
-
- snd_tscm_stream_stop_duplex(tscm);
- snd_tscm_stream_release_duplex(tscm);
-
- mutex_unlock(&tscm->mutex);
-
- return snd_pcm_lib_free_vmalloc_buffer(substream);
-}
-
-static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
+static int pcm_hw_free(struct snd_pcm_substream *substream)
{
struct snd_tscm *tscm = substream->private_data;
@@ -270,8 +229,8 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
- .hw_params = pcm_capture_hw_params,
- .hw_free = pcm_capture_hw_free,
+ .hw_params = pcm_hw_params,
+ .hw_free = pcm_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
@@ -282,8 +241,8 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
- .hw_params = pcm_playback_hw_params,
- .hw_free = pcm_playback_hw_free,
+ .hw_params = pcm_hw_params,
+ .hw_free = pcm_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 08/15] ALSA: fireface: add protocol-specific operation to allocate isochronous resources
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (6 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 07/15] ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free callbacks Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 09/15] ALSA: fireface: support allocate_resources operation in ff800 protocol Takashi Sakamoto
` (7 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
This commit is a part of preparation to perform allocation/release
of isochronous channels in pcm.hw_params/hw_free callbacks.
In ALSA fireface driver, the allocation of isochronous resources is
programmed in each implementation of protocol. This commit adds
protocol-specific operation for the allocation separated from
the operation to begin session.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/fireface/ff-stream.c | 4 ++++
sound/firewire/fireface/ff.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c
index a8a90f1ae09e..740963e4e1c9 100644
--- a/sound/firewire/fireface/ff-stream.c
+++ b/sound/firewire/fireface/ff-stream.c
@@ -156,6 +156,10 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
if (err < 0)
return err;
+ err = ff->spec->protocol->allocate_resources(ff, rate);
+ if (err < 0)
+ goto error;
+
err = ff->spec->protocol->begin_session(ff, rate);
if (err < 0)
goto error;
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h
index ed8fea0ff5e1..c478103388a2 100644
--- a/sound/firewire/fireface/ff.h
+++ b/sound/firewire/fireface/ff.h
@@ -113,6 +113,7 @@ struct snd_ff_protocol {
int (*get_clock)(struct snd_ff *ff, unsigned int *rate,
enum snd_ff_clock_src *src);
int (*switch_fetching_mode)(struct snd_ff *ff, bool enable);
+ int (*allocate_resources)(struct snd_ff *ff, unsigned int rate);
int (*begin_session)(struct snd_ff *ff, unsigned int rate);
void (*finish_session)(struct snd_ff *ff);
void (*dump_status)(struct snd_ff *ff, struct snd_info_buffer *buffer);
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 09/15] ALSA: fireface: support allocate_resources operation in ff800 protocol
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (7 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 08/15] ALSA: fireface: add protocol-specific operation to allocate isochronous resources Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 10/15] ALSA: fireface: support allocate_resources operation in ff400 protocol Takashi Sakamoto
` (6 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
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 ff800 protocol.
As I noted in commit fc716397a5c7 ("ALSA: fireface: add support for
packet streaming on Fireface 800"), this unit allocates isochronous
resources for tx stream voluntarily. Therefore, this commit is to
maintain isochronous rsources for rx stream. In the callback,
sampling transfer frequency is configured to the device as well.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/fireface/ff-protocol-former.c | 46 ++++++++++----------
1 file changed, 22 insertions(+), 24 deletions(-)
diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c
index 8d1c2c6e907b..11575d17d6cc 100644
--- a/sound/firewire/fireface/ff-protocol-former.c
+++ b/sound/firewire/fireface/ff-protocol-former.c
@@ -293,27 +293,6 @@ static int former_fill_midi_msg(struct snd_ff *ff,
#define FF800_TX_PACKET_ISOC_CH 0x0000801c0008
-static int allocate_rx_resources(struct snd_ff *ff)
-{
- u32 data;
- __le32 reg;
- int err;
-
- // Controllers should allocate isochronous resources for rx stream.
- 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)
- return err;
-
- // Set isochronous channel and the number of quadlets of rx packets.
- data = ff->rx_stream.data_block_quadlets << 3;
- data = (data << 8) | ff->rx_resources.channel;
- reg = cpu_to_le32(data);
- return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF800_RX_PACKET_FORMAT, ®, sizeof(reg), 0);
-}
-
static int allocate_tx_resources(struct snd_ff *ff)
{
__le32 reg;
@@ -355,8 +334,9 @@ static int allocate_tx_resources(struct snd_ff *ff)
return 0;
}
-static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
+static int ff800_allocate_resources(struct snd_ff *ff, unsigned int rate)
{
+ u32 data;
__le32 reg;
int err;
@@ -371,14 +351,31 @@ static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
// Let's sleep for a bit.
msleep(100);
- err = allocate_rx_resources(ff);
+ // Controllers should allocate isochronous resources for rx stream.
+ 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)
return err;
- err = allocate_tx_resources(ff);
+ // Set isochronous channel and the number of quadlets of rx packets.
+ // This should be done before the allocation of tx resources to avoid
+ // periodical noise.
+ data = ff->rx_stream.data_block_quadlets << 3;
+ data = (data << 8) | ff->rx_resources.channel;
+ reg = cpu_to_le32(data);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF800_RX_PACKET_FORMAT, ®, sizeof(reg), 0);
if (err < 0)
return err;
+ return allocate_tx_resources(ff);
+}
+
+static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
+{
+ __le32 reg;
+
reg = cpu_to_le32(0x80000000);
reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets);
if (fw_parent_device(ff->unit)->max_speed == SCODE_800)
@@ -420,6 +417,7 @@ const struct snd_ff_protocol snd_ff_protocol_ff800 = {
.fill_midi_msg = former_fill_midi_msg,
.get_clock = former_get_clock,
.switch_fetching_mode = former_switch_fetching_mode,
+ .allocate_resources = ff800_allocate_resources,
.begin_session = ff800_begin_session,
.finish_session = ff800_finish_session,
.dump_status = former_dump_status,
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 10/15] ALSA: fireface: support allocate_resources operation in ff400 protocol
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (8 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 09/15] ALSA: fireface: support allocate_resources operation in ff800 protocol Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 11/15] ALSA: fireface: support allocate_resources operation in latter protocol Takashi Sakamoto
` (5 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
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 ff400 protocol.
In this callback, sampling transfer frequency is configured to the
device as well.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/fireface/ff-protocol-former.c | 36 +++++++++-----------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c
index 11575d17d6cc..0517eb718f54 100644
--- a/sound/firewire/fireface/ff-protocol-former.c
+++ b/sound/firewire/fireface/ff-protocol-former.c
@@ -429,12 +429,11 @@ const struct snd_ff_protocol snd_ff_protocol_ff800 = {
#define FF400_TX_PACKET_FORMAT 0x00008010050cull
#define FF400_ISOC_COMM_STOP 0x000080100510ull
-/*
- * Fireface 400 manages isochronous channel number in 3 bit field. Therefore,
- * we can allocate between 0 and 7 channel.
- */
-static int keep_resources(struct snd_ff *ff, unsigned int rate)
+// Fireface 400 manages isochronous channel number in 3 bit field. Therefore,
+// we can allocate between 0 and 7 channel.
+static int ff400_allocate_resources(struct snd_ff *ff, unsigned int rate)
{
+ __le32 reg;
enum snd_ff_stream_mode mode;
int i;
int err;
@@ -447,11 +446,20 @@ static int keep_resources(struct snd_ff *ff, unsigned int rate)
if (i >= CIP_SFC_COUNT)
return -EINVAL;
+ // Set the number of data blocks transferred in a second.
+ reg = cpu_to_le32(rate);
+ err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
+ FF400_STF, ®, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
+ msleep(100);
+
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),
@@ -459,7 +467,7 @@ static int keep_resources(struct snd_ff *ff, unsigned int rate)
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),
@@ -475,19 +483,6 @@ static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
__le32 reg;
int err;
- err = keep_resources(ff, rate);
- if (err < 0)
- return err;
-
- /* Set the number of data blocks transferred in a second. */
- reg = cpu_to_le32(rate);
- err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
- FF400_STF, ®, sizeof(reg), 0);
- if (err < 0)
- return err;
-
- msleep(100);
-
/*
* Set isochronous channel and the number of quadlets of received
* packets.
@@ -589,6 +584,7 @@ const struct snd_ff_protocol snd_ff_protocol_ff400 = {
.fill_midi_msg = former_fill_midi_msg,
.get_clock = former_get_clock,
.switch_fetching_mode = former_switch_fetching_mode,
+ .allocate_resources = ff400_allocate_resources,
.begin_session = ff400_begin_session,
.finish_session = ff400_finish_session,
.dump_status = former_dump_status,
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 11/15] ALSA: fireface: support allocate_resources operation in latter protocol
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (9 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 10/15] ALSA: fireface: support allocate_resources operation in ff400 protocol Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 12/15] ALSA: fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (4 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
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>
---
sound/firewire/fireface/ff-protocol-latter.c | 113 +++++++++----------
1 file changed, 56 insertions(+), 57 deletions(-)
diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c
index c8236ff89b7f..3d12ba5b2a9b 100644
--- a/sound/firewire/fireface/ff-protocol-latter.c
+++ b/sound/firewire/fireface/ff-protocol-latter.c
@@ -97,25 +97,64 @@ 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;
+ 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, ®, 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),
@@ -123,7 +162,7 @@ static int keep_resources(struct snd_ff *ff, unsigned int rate)
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),
@@ -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, ®, 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,
@@ -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,
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 12/15] ALSA: fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (10 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 11/15] ALSA: fireface: support allocate_resources operation in latter protocol Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 13/15] ALSA: fireface: update isochronous resources when starting packet streaming after bus-reset Takashi Sakamoto
` (3 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
Once allocated, isochronous resources are available for packet
streaming, even if the streaming is cancelled. For this reason,
current implementation handles allocation of the resources and
starting packet streaming at the same time. However, this brings
complicated procedure to start packet streaming.
This commit separates the allocation and starting. The allocation is
done in pcm.hw_params callback and available till pcm.hw_free callback.
Even if any XRUN occurs, pcm.prepare callback is done to restart
packet streaming for allocated the resources.
There are two points to stop packet streaming; in pcm.hw_params and
pcm.prepare callbacks.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/fireface/ff-pcm.c | 18 ++++++--
sound/firewire/fireface/ff-stream.c | 67 ++++++++++++++++++-----------
sound/firewire/fireface/ff.h | 2 +
3 files changed, 57 insertions(+), 30 deletions(-)
diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c
index 5adf04b95c04..53477404a58f 100644
--- a/sound/firewire/fireface/ff-pcm.c
+++ b/sound/firewire/fireface/ff-pcm.c
@@ -211,8 +211,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
return err;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ unsigned int rate = params_rate(hw_params);
+
mutex_lock(&ff->mutex);
- ff->substreams_counter++;
+ err = snd_ff_stream_reserve_duplex(ff, rate);
+ if (err >= 0)
+ ++ff->substreams_counter;
mutex_unlock(&ff->mutex);
}
@@ -231,8 +235,12 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
return err;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+ unsigned int rate = params_rate(hw_params);
+
mutex_lock(&ff->mutex);
- ff->substreams_counter++;
+ err = snd_ff_stream_reserve_duplex(ff, rate);
+ if (err >= 0)
+ ++ff->substreams_counter;
mutex_unlock(&ff->mutex);
}
@@ -246,9 +254,10 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&ff->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- ff->substreams_counter--;
+ --ff->substreams_counter;
snd_ff_stream_stop_duplex(ff);
+ snd_ff_stream_release_duplex(ff);
mutex_unlock(&ff->mutex);
@@ -262,9 +271,10 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&ff->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- ff->substreams_counter--;
+ --ff->substreams_counter;
snd_ff_stream_stop_duplex(ff);
+ snd_ff_stream_release_duplex(ff);
mutex_unlock(&ff->mutex);
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c
index 740963e4e1c9..d9d1b469a8e9 100644
--- a/sound/firewire/fireface/ff-stream.c
+++ b/sound/firewire/fireface/ff-stream.c
@@ -31,12 +31,6 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
return 0;
}
-static void release_resources(struct snd_ff *ff)
-{
- fw_iso_resources_free(&ff->tx_resources);
- fw_iso_resources_free(&ff->rx_resources);
-}
-
static inline void finish_session(struct snd_ff *ff)
{
ff->spec->protocol->finish_session(ff);
@@ -104,36 +98,27 @@ void snd_ff_stream_destroy_duplex(struct snd_ff *ff)
destroy_stream(ff, AMDTP_OUT_STREAM);
}
-int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
+int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate)
{
unsigned int curr_rate;
enum snd_ff_clock_src src;
int err;
- if (ff->substreams_counter == 0)
- return 0;
-
err = ff->spec->protocol->get_clock(ff, &curr_rate, &src);
if (err < 0)
return err;
- if (curr_rate != rate ||
- amdtp_streaming_error(&ff->tx_stream) ||
- amdtp_streaming_error(&ff->rx_stream)) {
- finish_session(ff);
+
+ if (ff->substreams_counter == 0 || curr_rate != rate) {
+ enum snd_ff_stream_mode mode;
+ int i;
amdtp_stream_stop(&ff->tx_stream);
amdtp_stream_stop(&ff->rx_stream);
- release_resources(ff);
- }
+ finish_session(ff);
- /*
- * Regardless of current source of clock signal, drivers transfer some
- * packets. Then, the device transfers packets.
- */
- if (!amdtp_stream_running(&ff->rx_stream)) {
- enum snd_ff_stream_mode mode;
- int i;
+ fw_iso_resources_free(&ff->tx_resources);
+ fw_iso_resources_free(&ff->rx_resources);
for (i = 0; i < CIP_SFC_COUNT; ++i) {
if (amdtp_rate_table[i] == rate)
@@ -158,8 +143,40 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
err = ff->spec->protocol->allocate_resources(ff, rate);
if (err < 0)
- goto error;
+ return err;
+ }
+
+ return 0;
+}
+
+void snd_ff_stream_release_duplex(struct snd_ff *ff)
+{
+ if (ff->substreams_counter == 0) {
+ fw_iso_resources_free(&ff->tx_resources);
+ fw_iso_resources_free(&ff->rx_resources);
+ }
+}
+
+int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
+{
+ int err;
+
+ if (ff->substreams_counter == 0)
+ return 0;
+ if (amdtp_streaming_error(&ff->tx_stream) ||
+ amdtp_streaming_error(&ff->rx_stream)) {
+ amdtp_stream_stop(&ff->tx_stream);
+ amdtp_stream_stop(&ff->rx_stream);
+
+ finish_session(ff);
+ }
+
+ /*
+ * Regardless of current source of clock signal, drivers transfer some
+ * packets. Then, the device transfers packets.
+ */
+ if (!amdtp_stream_running(&ff->rx_stream)) {
err = ff->spec->protocol->begin_session(ff, rate);
if (err < 0)
goto error;
@@ -201,7 +218,6 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
amdtp_stream_stop(&ff->rx_stream);
finish_session(ff);
- release_resources(ff);
return err;
}
@@ -214,7 +230,6 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff)
amdtp_stream_stop(&ff->tx_stream);
amdtp_stream_stop(&ff->rx_stream);
finish_session(ff);
- release_resources(ff);
}
void snd_ff_stream_update_duplex(struct snd_ff *ff)
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h
index c478103388a2..fe5739ee1c88 100644
--- a/sound/firewire/fireface/ff.h
+++ b/sound/firewire/fireface/ff.h
@@ -138,6 +138,8 @@ 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_reserve_duplex(struct snd_ff *ff, unsigned int rate);
+void snd_ff_stream_release_duplex(struct snd_ff *ff);
int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate);
void snd_ff_stream_stop_duplex(struct snd_ff *ff);
void snd_ff_stream_update_duplex(struct snd_ff *ff);
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 13/15] ALSA: fireface: update isochronous resources when starting packet streaming after bus-reset
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (11 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 12/15] ALSA: fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 14/15] ALSA: fireface: minor code refactoring to finish streaming session Takashi Sakamoto
` (2 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
After bus reset, isochronous resource manager releases all of allocated
isochronous resources. The nodes to restart packet streaming should
request reallocation of the resources.
However, between the bus-reset and invocation of 'struct fw_driver.update'
handler, ALSA PCM application can detect this situation by XRUN because
the target device cancelled to transmit packets once bus-reset occurs.
Due to the above mechanism, ALSA fireface driver just stops packet
streaming in the update handler, thus pcm.prepare handler should
request the reallocation.
This commit requests the reallocation in pcm.prepare callback when
bus generation is changed.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/fireface/ff-protocol-former.c | 34 ++++++++++++++------
sound/firewire/fireface/ff-protocol-latter.c | 11 +++++++
sound/firewire/fireface/ff-stream.c | 5 +--
3 files changed, 36 insertions(+), 14 deletions(-)
diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c
index 0517eb718f54..bf44cad7985e 100644
--- a/sound/firewire/fireface/ff-protocol-former.c
+++ b/sound/firewire/fireface/ff-protocol-former.c
@@ -374,8 +374,15 @@ static int ff800_allocate_resources(struct snd_ff *ff, unsigned int rate)
static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
{
+ unsigned int generation = ff->rx_resources.generation;
__le32 reg;
+ if (generation != fw_parent_device(ff->unit)->card->generation) {
+ int err = fw_iso_resources_update(&ff->rx_resources);
+ if (err < 0)
+ return err;
+ }
+
reg = cpu_to_le32(0x80000000);
reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets);
if (fw_parent_device(ff->unit)->max_speed == SCODE_800)
@@ -480,13 +487,22 @@ static int ff400_allocate_resources(struct snd_ff *ff, unsigned int rate)
static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
{
+ unsigned int generation = ff->rx_resources.generation;
__le32 reg;
int err;
- /*
- * Set isochronous channel and the number of quadlets of received
- * packets.
- */
+ if (generation != fw_parent_device(ff->unit)->card->generation) {
+ err = fw_iso_resources_update(&ff->tx_resources);
+ if (err < 0)
+ return err;
+
+ err = fw_iso_resources_update(&ff->rx_resources);
+ if (err < 0)
+ return err;
+ }
+
+ // Set isochronous channel and the number of quadlets of received
+ // packets.
reg = cpu_to_le32(((ff->rx_stream.data_block_quadlets << 3) << 8) |
ff->rx_resources.channel);
err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
@@ -494,11 +510,9 @@ static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
if (err < 0)
return err;
- /*
- * Set isochronous channel and the number of quadlets of transmitted
- * packet.
- */
- /* TODO: investigate the purpose of this 0x80. */
+ // Set isochronous channel and the number of quadlets of transmitted
+ // packet.
+ // TODO: investigate the purpose of this 0x80.
reg = cpu_to_le32((0x80 << 24) |
(ff->tx_resources.channel << 5) |
(ff->tx_stream.data_block_quadlets));
@@ -507,7 +521,7 @@ static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
if (err < 0)
return err;
- /* Allow to transmit packets. */
+ // Allow to transmit packets.
reg = cpu_to_le32(0x00000001);
return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
FF400_ISOC_COMM_START, ®, sizeof(reg), 0);
diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c
index 3d12ba5b2a9b..8d6ebb638e93 100644
--- a/sound/firewire/fireface/ff-protocol-latter.c
+++ b/sound/firewire/fireface/ff-protocol-latter.c
@@ -175,6 +175,7 @@ static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate)
static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
{
+ unsigned int generation = ff->rx_resources.generation;
unsigned int flag;
u32 data;
__le32 reg;
@@ -189,6 +190,16 @@ static int latter_begin_session(struct snd_ff *ff, unsigned int rate)
else
return -EINVAL;
+ if (generation != fw_parent_device(ff->unit)->card->generation) {
+ err = fw_iso_resources_update(&ff->tx_resources);
+ if (err < 0)
+ return err;
+
+ err = fw_iso_resources_update(&ff->rx_resources);
+ 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,
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c
index d9d1b469a8e9..4f40dfb11979 100644
--- a/sound/firewire/fireface/ff-stream.c
+++ b/sound/firewire/fireface/ff-stream.c
@@ -234,15 +234,12 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff)
void snd_ff_stream_update_duplex(struct snd_ff *ff)
{
- /* The device discontinue to transfer packets. */
+ // The device discontinue to transfer packets.
amdtp_stream_pcm_abort(&ff->tx_stream);
amdtp_stream_stop(&ff->tx_stream);
amdtp_stream_pcm_abort(&ff->rx_stream);
amdtp_stream_stop(&ff->rx_stream);
-
- fw_iso_resources_update(&ff->tx_resources);
- fw_iso_resources_update(&ff->rx_resources);
}
void snd_ff_stream_lock_changed(struct snd_ff *ff)
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 14/15] ALSA: fireface: minor code refactoring to finish streaming session
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (12 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 13/15] ALSA: fireface: update isochronous resources when starting packet streaming after bus-reset Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 15/15] ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-11 9:37 ` [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in " Takashi Iwai
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
The operation to finish packet streaming corresponds to stopping
isochronous contexts.
This commit applies code refactoring to move codes to stop into
a helper function to finish the session.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/fireface/ff-stream.c | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c
index 4f40dfb11979..884705ecf940 100644
--- a/sound/firewire/fireface/ff-stream.c
+++ b/sound/firewire/fireface/ff-stream.c
@@ -33,6 +33,9 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
static inline void finish_session(struct snd_ff *ff)
{
+ amdtp_stream_stop(&ff->tx_stream);
+ amdtp_stream_stop(&ff->rx_stream);
+
ff->spec->protocol->finish_session(ff);
ff->spec->protocol->switch_fetching_mode(ff, false);
}
@@ -112,9 +115,6 @@ int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate)
enum snd_ff_stream_mode mode;
int i;
- amdtp_stream_stop(&ff->tx_stream);
- amdtp_stream_stop(&ff->rx_stream);
-
finish_session(ff);
fw_iso_resources_free(&ff->tx_resources);
@@ -165,12 +165,8 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
return 0;
if (amdtp_streaming_error(&ff->tx_stream) ||
- amdtp_streaming_error(&ff->rx_stream)) {
- amdtp_stream_stop(&ff->tx_stream);
- amdtp_stream_stop(&ff->rx_stream);
-
+ amdtp_streaming_error(&ff->rx_stream))
finish_session(ff);
- }
/*
* Regardless of current source of clock signal, drivers transfer some
@@ -214,9 +210,6 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
return 0;
error:
- amdtp_stream_stop(&ff->tx_stream);
- amdtp_stream_stop(&ff->rx_stream);
-
finish_session(ff);
return err;
@@ -224,12 +217,8 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate)
void snd_ff_stream_stop_duplex(struct snd_ff *ff)
{
- if (ff->substreams_counter > 0)
- return;
-
- amdtp_stream_stop(&ff->tx_stream);
- amdtp_stream_stop(&ff->rx_stream);
- finish_session(ff);
+ if (ff->substreams_counter == 0)
+ finish_session(ff);
}
void snd_ff_stream_update_duplex(struct snd_ff *ff)
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 15/15] ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (13 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 14/15] ALSA: fireface: minor code refactoring to finish streaming session Takashi Sakamoto
@ 2019-06-02 7:12 ` Takashi Sakamoto
2019-06-11 9:37 ` [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in " Takashi Iwai
15 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-02 7:12 UTC (permalink / raw)
To: clemens, tiwai; +Cc: alsa-devel
The pairs of pcm.hw_params callbacks and .hw_free callbacks for both
direction have no differences.
This commit unifies the pairs.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
sound/firewire/fireface/ff-pcm.c | 55 ++++----------------------------
1 file changed, 7 insertions(+), 48 deletions(-)
diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c
index 53477404a58f..938985c2d4a8 100644
--- a/sound/firewire/fireface/ff-pcm.c
+++ b/sound/firewire/fireface/ff-pcm.c
@@ -199,8 +199,8 @@ static int pcm_close(struct snd_pcm_substream *substream)
return 0;
}
-static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
+static int pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
struct snd_ff *ff = substream->private_data;
int err;
@@ -223,48 +223,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_ff *ff = substream->private_data;
- int err;
-
- err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
- params_buffer_bytes(hw_params));
- if (err < 0)
- return err;
-
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- unsigned int rate = params_rate(hw_params);
-
- mutex_lock(&ff->mutex);
- err = snd_ff_stream_reserve_duplex(ff, rate);
- if (err >= 0)
- ++ff->substreams_counter;
- mutex_unlock(&ff->mutex);
- }
-
- return 0;
-}
-
-static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_ff *ff = substream->private_data;
-
- mutex_lock(&ff->mutex);
-
- if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
- --ff->substreams_counter;
-
- snd_ff_stream_stop_duplex(ff);
- snd_ff_stream_release_duplex(ff);
-
- mutex_unlock(&ff->mutex);
-
- return snd_pcm_lib_free_vmalloc_buffer(substream);
-}
-
-static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
+static int pcm_hw_free(struct snd_pcm_substream *substream)
{
struct snd_ff *ff = substream->private_data;
@@ -385,8 +344,8 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff)
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
- .hw_params = pcm_capture_hw_params,
- .hw_free = pcm_capture_hw_free,
+ .hw_params = pcm_hw_params,
+ .hw_free = pcm_hw_free,
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
@@ -397,8 +356,8 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff)
.open = pcm_open,
.close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
- .hw_params = pcm_playback_hw_params,
- .hw_free = pcm_playback_hw_free,
+ .hw_params = pcm_hw_params,
+ .hw_free = pcm_hw_free,
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
--
2.20.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
` (14 preceding siblings ...)
2019-06-02 7:12 ` [PATCH 15/15] ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks Takashi Sakamoto
@ 2019-06-11 9:37 ` Takashi Iwai
2019-06-11 9:59 ` Takashi Sakamoto
15 siblings, 1 reply; 18+ messages in thread
From: Takashi Iwai @ 2019-06-11 9:37 UTC (permalink / raw)
To: Takashi Sakamoto; +Cc: alsa-devel, clemens
On Sun, 02 Jun 2019 09:12:44 +0200,
Takashi Sakamoto wrote:
>
> Hi,
>
> This patchset is a part of series of patches for all of drivers in
> ALSA firewire stack to reserve/release isochronous resources in
> pcm.hw_params/hw_free callbacks.
>
> In current implementation, the resources are reserved at the same time
> to start packet streaming, and released at the same time to stop packet
> streaming. However, once allocated, the resources are available
> independent of lifetime of packet streaming.
>
> The isochronous resources are the resources of IEEE 1394 bus. On the
> other side of view, it's a kind of resources of hardware to maintain
> the bus (isochronous resource manager). For this kind of reservation and
> release, hw_params and hw_free operations are suitable in ALSA PCM
> interface.
>
> Ideally, the operation to reserve/release isochronous resource should
> be separated from the operation to start/stop packet streaming. However,
> IEEE 1394 bus has reset event. Once reset occurs, isochronous resource
> manager releases allocated resources. The resources should be
> reallocated by requesters themselves. For this reason, in this patchset,
> bus generation is checked before starting packet streaming. If
> generation is updated, reallocation is requested to isochronous
> resource manager, then packet streaming starts.
>
> Takashi Sakamoto (15):
> ALSA: firewire-tascam: code refactoring for registration of
> isochronous channels
> ALSA: firewire-tascam: code refactoring for reservation of isochronous
> resources
> ALSA: firewire-tascam: code refactoring for release of isochronous
> resources
> ALSA: firewire-tascam: reserve/release isochronous resources in
> pcm.hw_params/hw_free callbacks
> ALSA: firewire-tascam: update isochronous resources when starting
> packet streaming after bus reset
> ALSA: firewire-tascam: minor code refactoring to finish streaming
> session
> ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free
> callbacks
> ALSA: fireface: add protocol-specific operation to allocate
> isochronous resources
> ALSA: fireface: support allocate_resources operation in ff800 protocol
> ALSA: fireface: support allocate_resources operation in ff400 protocol
> ALSA: fireface: support allocate_resources operation in latter
> protocol
> ALSA: fireface: reserve/release isochronous resources in
> pcm.hw_params/hw_free callbacks
> ALSA: fireface: update isochronous resources when starting packet
> streaming after bus-reset
> ALSA: fireface: minor code refactoring to finish streaming session
> ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks
Applied all 15 patches now. Thanks.
Takashi
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks
2019-06-11 9:37 ` [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in " Takashi Iwai
@ 2019-06-11 9:59 ` Takashi Sakamoto
0 siblings, 0 replies; 18+ messages in thread
From: Takashi Sakamoto @ 2019-06-11 9:59 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel, clemens
On Tue, Jun 11, 2019 at 11:37:25AM +0200, Takashi Iwai wrote:
> On Sun, 02 Jun 2019 09:12:44 +0200,
> Takashi Sakamoto wrote:
> >
> > Hi,
> >
> > This patchset is a part of series of patches for all of drivers in
> > ALSA firewire stack to reserve/release isochronous resources in
> > pcm.hw_params/hw_free callbacks.
> >
> > In current implementation, the resources are reserved at the same time
> > to start packet streaming, and released at the same time to stop packet
> > streaming. However, once allocated, the resources are available
> > independent of lifetime of packet streaming.
> >
> > The isochronous resources are the resources of IEEE 1394 bus. On the
> > other side of view, it's a kind of resources of hardware to maintain
> > the bus (isochronous resource manager). For this kind of reservation and
> > release, hw_params and hw_free operations are suitable in ALSA PCM
> > interface.
> >
> > Ideally, the operation to reserve/release isochronous resource should
> > be separated from the operation to start/stop packet streaming. However,
> > IEEE 1394 bus has reset event. Once reset occurs, isochronous resource
> > manager releases allocated resources. The resources should be
> > reallocated by requesters themselves. For this reason, in this patchset,
> > bus generation is checked before starting packet streaming. If
> > generation is updated, reallocation is requested to isochronous
> > resource manager, then packet streaming starts.
> >
> > Takashi Sakamoto (15):
> > ALSA: firewire-tascam: code refactoring for registration of
> > isochronous channels
> > ALSA: firewire-tascam: code refactoring for reservation of isochronous
> > resources
> > ALSA: firewire-tascam: code refactoring for release of isochronous
> > resources
> > ALSA: firewire-tascam: reserve/release isochronous resources in
> > pcm.hw_params/hw_free callbacks
> > ALSA: firewire-tascam: update isochronous resources when starting
> > packet streaming after bus reset
> > ALSA: firewire-tascam: minor code refactoring to finish streaming
> > session
> > ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free
> > callbacks
> > ALSA: fireface: add protocol-specific operation to allocate
> > isochronous resources
> > ALSA: fireface: support allocate_resources operation in ff800 protocol
> > ALSA: fireface: support allocate_resources operation in ff400 protocol
> > ALSA: fireface: support allocate_resources operation in latter
> > protocol
> > ALSA: fireface: reserve/release isochronous resources in
> > pcm.hw_params/hw_free callbacks
> > ALSA: fireface: update isochronous resources when starting packet
> > streaming after bus-reset
> > ALSA: fireface: minor code refactoring to finish streaming session
> > ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks
>
> Applied all 15 patches now. Thanks.
Welcome back ;)
I've already prepared similar patchsets for the other drivers in ALSA
firewire stack. You'll receive the patchset several times in this week.
I'm happy if you review and apply them.
Thanks
Takashi Sakamoto
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2019-06-11 9:59 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-02 7:12 [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 01/15] ALSA: firewire-tascam: code refactoring for registration of isochronous channels Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 02/15] ALSA: firewire-tascam: code refactoring for reservation of isochronous resources Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 03/15] ALSA: firewire-tascam: code refactoring for release " Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 04/15] ALSA: firewire-tascam: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 05/15] ALSA: firewire-tascam: update isochronous resources when starting packet streaming after bus reset Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 06/15] ALSA: firewire-tascam: minor code refactoring to finish streaming session Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 07/15] ALSA: firewire-tascam: code refactoring for pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 08/15] ALSA: fireface: add protocol-specific operation to allocate isochronous resources Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 09/15] ALSA: fireface: support allocate_resources operation in ff800 protocol Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 10/15] ALSA: fireface: support allocate_resources operation in ff400 protocol Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 11/15] ALSA: fireface: support allocate_resources operation in latter protocol Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 12/15] ALSA: fireface: reserve/release isochronous resources in pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 13/15] ALSA: fireface: update isochronous resources when starting packet streaming after bus-reset Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 14/15] ALSA: fireface: minor code refactoring to finish streaming session Takashi Sakamoto
2019-06-02 7:12 ` [PATCH 15/15] ALSA: fireface: code refactoring for pcm.hw_params/hw_free callbacks Takashi Sakamoto
2019-06-11 9:37 ` [PATCH 00/15] ALSA: firewire-tascam/fireface: reserve/release isochronous resources in " Takashi Iwai
2019-06-11 9:59 ` Takashi Sakamoto
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.