From 071106ecf68c401173c58808b1cf5f68cc50d390 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 05 Jan 2024 08:39:27 +0000 Subject: [PATCH] change wifi driver to cypress --- kernel/sound/firewire/tascam/tascam-stream.c | 339 +++++++++++++++++++++++++++++++------------------------- 1 files changed, 188 insertions(+), 151 deletions(-) diff --git a/kernel/sound/firewire/tascam/tascam-stream.c b/kernel/sound/firewire/tascam/tascam-stream.c index a1308f1..47de972 100644 --- a/kernel/sound/firewire/tascam/tascam-stream.c +++ b/kernel/sound/firewire/tascam/tascam-stream.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * tascam-stream.c - a part of driver for TASCAM FireWire series * * Copyright (c) 2015 Takashi Sakamoto - * - * Licensed under the terms of the GNU General Public License, version 2. */ #include <linux/delay.h> @@ -180,7 +179,7 @@ __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, @@ -188,11 +187,7 @@ 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) @@ -209,12 +204,49 @@ 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) { __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, @@ -230,7 +262,7 @@ 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, @@ -238,7 +270,7 @@ 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, @@ -246,169 +278,182 @@ ®, sizeof(reg), 0); } -static void release_resources(struct snd_tscm *tscm) +static int keep_resources(struct snd_tscm *tscm, unsigned int rate, + struct amdtp_stream *stream) { - __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. */ - 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; + 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; - /* 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; + return fw_iso_resources_allocate(resources, + amdtp_stream_get_max_payload(stream), + fw_parent_device(tscm->unit)->max_speed); +} - /* 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; +static int init_stream(struct snd_tscm *tscm, struct amdtp_stream *s) +{ + struct fw_iso_resources *resources; + enum amdtp_stream_direction dir; + unsigned int pcm_channels; + int 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) - goto error; + if (s == &tscm->tx_stream) { + resources = &tscm->tx_resources; + dir = AMDTP_IN_STREAM; + pcm_channels = tscm->spec->pcm_capture_analog_channels; + } else { + resources = &tscm->rx_resources; + dir = AMDTP_OUT_STREAM; + pcm_channels = tscm->spec->pcm_playback_analog_channels; + } - return 0; -error: - release_resources(tscm); + if (tscm->spec->has_adat) + pcm_channels += 8; + if (tscm->spec->has_spdif) + pcm_channels += 2; + + err = fw_iso_resources_init(resources, tscm->unit); + if (err < 0) + return err; + + err = amdtp_tscm_init(s, tscm->unit, dir, pcm_channels); + if (err < 0) + fw_iso_resources_free(resources); + return err; +} + +static void destroy_stream(struct snd_tscm *tscm, struct amdtp_stream *s) +{ + amdtp_stream_destroy(s); + + if (s == &tscm->tx_stream) + fw_iso_resources_destroy(&tscm->tx_resources); + else + fw_iso_resources_destroy(&tscm->rx_resources); } int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) { - unsigned int pcm_channels; int err; - /* For out-stream. */ - err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit); - if (err < 0) - return err; - pcm_channels = tscm->spec->pcm_playback_analog_channels; - if (tscm->spec->has_adat) - pcm_channels += 8; - if (tscm->spec->has_spdif) - pcm_channels += 2; - err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM, - pcm_channels); + err = init_stream(tscm, &tscm->tx_stream); if (err < 0) return err; - /* For in-stream. */ - err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit); - if (err < 0) + err = init_stream(tscm, &tscm->rx_stream); + if (err < 0) { + destroy_stream(tscm, &tscm->tx_stream); return err; - pcm_channels = tscm->spec->pcm_capture_analog_channels; - if (tscm->spec->has_adat) - pcm_channels += 8; - if (tscm->spec->has_spdif) - pcm_channels += 2; - err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM, - pcm_channels); - if (err < 0) - amdtp_stream_destroy(&tscm->rx_stream); + } + + err = amdtp_domain_init(&tscm->domain); + if (err < 0) { + destroy_stream(tscm, &tscm->tx_stream); + destroy_stream(tscm, &tscm->rx_stream); + } 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); - amdtp_stream_stop(&tscm->tx_stream); + amdtp_domain_stop(&tscm->domain); + amdtp_stream_pcm_abort(&tscm->tx_stream); amdtp_stream_pcm_abort(&tscm->rx_stream); - amdtp_stream_stop(&tscm->rx_stream); } -/* - * This function should be called before starting streams or after stopping - * streams. - */ +// This function should be called before starting streams or after stopping +// streams. void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) { - amdtp_stream_destroy(&tscm->rx_stream); - amdtp_stream_destroy(&tscm->tx_stream); + amdtp_domain_destroy(&tscm->domain); - fw_iso_resources_destroy(&tscm->rx_resources); - fw_iso_resources_destroy(&tscm->tx_resources); + destroy_stream(tscm, &tscm->rx_stream); + destroy_stream(tscm, &tscm->tx_stream); +} + +int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate, + unsigned int frames_per_period, + unsigned int frames_per_buffer) +{ + unsigned int curr_rate; + int err; + + err = snd_tscm_stream_get_rate(tscm, &curr_rate); + if (err < 0) + return err; + + if (tscm->substreams_counter == 0 || rate != curr_rate) { + amdtp_domain_stop(&tscm->domain); + + finish_session(tscm); + + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); + + err = set_clock(tscm, rate, INT_MAX); + if (err < 0) + return err; + + err = keep_resources(tscm, rate, &tscm->tx_stream); + if (err < 0) + return err; + + err = keep_resources(tscm, rate, &tscm->rx_stream); + if (err < 0) { + fw_iso_resources_free(&tscm->tx_resources); + return err; + } + + err = amdtp_domain_set_events_per_period(&tscm->domain, + frames_per_period, frames_per_buffer); + if (err < 0) { + fw_iso_resources_free(&tscm->tx_resources); + fw_iso_resources_free(&tscm->rx_resources); + return err; + } + } + + return 0; } int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) { - unsigned int curr_rate; + unsigned int generation = tscm->rx_resources.generation; 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) || + if (amdtp_streaming_error(&tscm->rx_stream) || amdtp_streaming_error(&tscm->tx_stream)) { + amdtp_domain_stop(&tscm->domain); finish_session(tscm); + } - amdtp_stream_stop(&tscm->rx_stream); - amdtp_stream_stop(&tscm->tx_stream); + if (generation != fw_parent_device(tscm->unit)->card->generation) { + err = fw_iso_resources_update(&tscm->tx_resources); + if (err < 0) + goto error; - release_resources(tscm); + err = fw_iso_resources_update(&tscm->rx_resources); + if (err < 0) + goto error; } if (!amdtp_stream_running(&tscm->rx_stream)) { - err = keep_resources(tscm, rate); - if (err < 0) - goto error; + int spd = fw_parent_device(tscm->unit)->max_speed; err = set_stream_formats(tscm, rate); if (err < 0) @@ -418,27 +463,23 @@ if (err < 0) goto error; - err = amdtp_stream_start(&tscm->rx_stream, - tscm->rx_resources.channel, - fw_parent_device(tscm->unit)->max_speed); + err = amdtp_domain_add_stream(&tscm->domain, &tscm->rx_stream, + tscm->rx_resources.channel, spd); + if (err < 0) + goto error; + + err = amdtp_domain_add_stream(&tscm->domain, &tscm->tx_stream, + tscm->tx_resources.channel, spd); + if (err < 0) + goto error; + + err = amdtp_domain_start(&tscm->domain, 0); if (err < 0) goto error; if (!amdtp_stream_wait_callback(&tscm->rx_stream, - CALLBACK_TIMEOUT)) { - err = -ETIMEDOUT; - goto error; - } - } - - if (!amdtp_stream_running(&tscm->tx_stream)) { - err = amdtp_stream_start(&tscm->tx_stream, - tscm->tx_resources.channel, - fw_parent_device(tscm->unit)->max_speed); - if (err < 0) - goto error; - - if (!amdtp_stream_wait_callback(&tscm->tx_stream, + CALLBACK_TIMEOUT) || + !amdtp_stream_wait_callback(&tscm->tx_stream, CALLBACK_TIMEOUT)) { err = -ETIMEDOUT; goto error; @@ -447,25 +488,21 @@ return 0; error: - amdtp_stream_stop(&tscm->rx_stream); - amdtp_stream_stop(&tscm->tx_stream); - + amdtp_domain_stop(&tscm->domain); finish_session(tscm); - release_resources(tscm); return err; } void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) { - if (tscm->substreams_counter > 0) - return; + if (tscm->substreams_counter == 0) { + amdtp_domain_stop(&tscm->domain); + finish_session(tscm); - amdtp_stream_stop(&tscm->tx_stream); - 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) -- Gitblit v1.6.2