From 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 22 Oct 2024 10:36:11 +0000 Subject: [PATCH] 修改4g拨号为QMI,需要在系统里后台执行quectel-CM --- kernel/sound/firewire/fireface/ff-stream.c | 252 +++++++++++++++++++++++++------------------------- 1 files changed, 127 insertions(+), 125 deletions(-) diff --git a/kernel/sound/firewire/fireface/ff-stream.c b/kernel/sound/firewire/fireface/ff-stream.c index 7888092..5452115 100644 --- a/kernel/sound/firewire/fireface/ff-stream.c +++ b/kernel/sound/firewire/fireface/ff-stream.c @@ -1,76 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ff-stream.c - a part of driver for RME Fireface series * * Copyright (c) 2015-2017 Takashi Sakamoto - * - * Licensed under the terms of the GNU General Public License, version 2. */ #include "ff.h" #define CALLBACK_TIMEOUT_MS 200 -static int get_rate_mode(unsigned int rate, unsigned int *mode) +int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, + enum snd_ff_stream_mode *mode) { - int i; + static const enum snd_ff_stream_mode modes[] = { + [CIP_SFC_32000] = SND_FF_STREAM_MODE_LOW, + [CIP_SFC_44100] = SND_FF_STREAM_MODE_LOW, + [CIP_SFC_48000] = SND_FF_STREAM_MODE_LOW, + [CIP_SFC_88200] = SND_FF_STREAM_MODE_MID, + [CIP_SFC_96000] = SND_FF_STREAM_MODE_MID, + [CIP_SFC_176400] = SND_FF_STREAM_MODE_HIGH, + [CIP_SFC_192000] = SND_FF_STREAM_MODE_HIGH, + }; - for (i = 0; i < CIP_SFC_COUNT; i++) { - if (amdtp_rate_table[i] == rate) - break; - } - - if (i == CIP_SFC_COUNT) + if (sfc >= CIP_SFC_COUNT) return -EINVAL; - *mode = ((int)i - 1) / 2; + *mode = modes[sfc]; return 0; -} - -/* - * 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) -{ - int mode; - int err; - - err = get_rate_mode(rate, &mode); - if (err < 0) - return err; - - /* Keep resources for in-stream. */ - err = amdtp_ff_set_parameters(&ff->tx_stream, rate, - ff->spec->pcm_capture_channels[mode]); - if (err < 0) - return err; - 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. */ - err = amdtp_ff_set_parameters(&ff->rx_stream, rate, - ff->spec->pcm_playback_channels[mode]); - if (err < 0) - return err; - 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 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) @@ -79,54 +36,61 @@ ff->spec->protocol->switch_fetching_mode(ff, false); } -static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) +static int init_stream(struct snd_ff *ff, struct amdtp_stream *s) { - int err; struct fw_iso_resources *resources; - struct amdtp_stream *stream; + enum amdtp_stream_direction dir; + int err; - if (dir == AMDTP_IN_STREAM) { + if (s == &ff->tx_stream) { resources = &ff->tx_resources; - stream = &ff->tx_stream; + dir = AMDTP_IN_STREAM; } else { resources = &ff->rx_resources; - stream = &ff->rx_stream; + dir = AMDTP_OUT_STREAM; } err = fw_iso_resources_init(resources, ff->unit); if (err < 0) return err; - err = amdtp_ff_init(stream, ff->unit, dir); + err = amdtp_ff_init(s, ff->unit, dir); if (err < 0) fw_iso_resources_destroy(resources); return err; } -static void destroy_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) +static void destroy_stream(struct snd_ff *ff, struct amdtp_stream *s) { - if (dir == AMDTP_IN_STREAM) { - amdtp_stream_destroy(&ff->tx_stream); + amdtp_stream_destroy(s); + + if (s == &ff->tx_stream) fw_iso_resources_destroy(&ff->tx_resources); - } else { - amdtp_stream_destroy(&ff->rx_stream); + else fw_iso_resources_destroy(&ff->rx_resources); - } } int snd_ff_stream_init_duplex(struct snd_ff *ff) { int err; - err = init_stream(ff, AMDTP_OUT_STREAM); + err = init_stream(ff, &ff->rx_stream); if (err < 0) - goto end; + return err; - err = init_stream(ff, AMDTP_IN_STREAM); - if (err < 0) - destroy_stream(ff, AMDTP_OUT_STREAM); -end: + err = init_stream(ff, &ff->tx_stream); + if (err < 0) { + destroy_stream(ff, &ff->rx_stream); + return err; + } + + err = amdtp_domain_init(&ff->domain); + if (err < 0) { + destroy_stream(ff, &ff->rx_stream); + destroy_stream(ff, &ff->tx_stream); + } + return err; } @@ -136,31 +100,82 @@ */ void snd_ff_stream_destroy_duplex(struct snd_ff *ff) { - destroy_stream(ff, AMDTP_IN_STREAM); - destroy_stream(ff, AMDTP_OUT_STREAM); + amdtp_domain_destroy(&ff->domain); + + destroy_stream(ff, &ff->rx_stream); + destroy_stream(ff, &ff->tx_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 frames_per_period, + unsigned int frames_per_buffer) { 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)) { + + if (ff->substreams_counter == 0 || curr_rate != rate) { + enum snd_ff_stream_mode mode; + int i; + + amdtp_domain_stop(&ff->domain); finish_session(ff); - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); + fw_iso_resources_free(&ff->tx_resources); + fw_iso_resources_free(&ff->rx_resources); - release_resources(ff); + 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; + + err = amdtp_ff_set_parameters(&ff->tx_stream, rate, + ff->spec->pcm_capture_channels[mode]); + if (err < 0) + return err; + + err = amdtp_ff_set_parameters(&ff->rx_stream, rate, + ff->spec->pcm_playback_channels[mode]); + if (err < 0) + return err; + + err = ff->spec->protocol->allocate_resources(ff, rate); + if (err < 0) + return err; + + err = amdtp_domain_set_events_per_period(&ff->domain, + frames_per_period, frames_per_buffer); + if (err < 0) { + fw_iso_resources_free(&ff->tx_resources); + fw_iso_resources_free(&ff->rx_resources); + return err; + } + } + + return 0; +} + +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_domain_stop(&ff->domain); + finish_session(ff); } /* @@ -168,21 +183,29 @@ * packets. Then, the device transfers packets. */ if (!amdtp_stream_running(&ff->rx_stream)) { - err = keep_resources(ff, rate); - if (err < 0) - goto error; + int spd = fw_parent_device(ff->unit)->max_speed; err = ff->spec->protocol->begin_session(ff, rate); if (err < 0) goto error; - err = amdtp_stream_start(&ff->rx_stream, - ff->rx_resources.channel, - fw_parent_device(ff->unit)->max_speed); + err = amdtp_domain_add_stream(&ff->domain, &ff->rx_stream, + ff->rx_resources.channel, spd); + if (err < 0) + goto error; + + err = amdtp_domain_add_stream(&ff->domain, &ff->tx_stream, + ff->tx_resources.channel, spd); + if (err < 0) + goto error; + + err = amdtp_domain_start(&ff->domain, 0); if (err < 0) goto error; if (!amdtp_stream_wait_callback(&ff->rx_stream, + CALLBACK_TIMEOUT_MS) || + !amdtp_stream_wait_callback(&ff->tx_stream, CALLBACK_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; @@ -193,53 +216,32 @@ goto error; } - if (!amdtp_stream_running(&ff->tx_stream)) { - err = amdtp_stream_start(&ff->tx_stream, - ff->tx_resources.channel, - fw_parent_device(ff->unit)->max_speed); - if (err < 0) - goto error; - - if (!amdtp_stream_wait_callback(&ff->tx_stream, - CALLBACK_TIMEOUT_MS)) { - err = -ETIMEDOUT; - goto error; - } - } - return 0; error: - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); - + amdtp_domain_stop(&ff->domain); finish_session(ff); - release_resources(ff); return err; } void snd_ff_stream_stop_duplex(struct snd_ff *ff) { - if (ff->substreams_counter > 0) - return; + if (ff->substreams_counter == 0) { + amdtp_domain_stop(&ff->domain); + finish_session(ff); - amdtp_stream_stop(&ff->tx_stream); - amdtp_stream_stop(&ff->rx_stream); - finish_session(ff); - release_resources(ff); + fw_iso_resources_free(&ff->tx_resources); + fw_iso_resources_free(&ff->rx_resources); + } } void snd_ff_stream_update_duplex(struct snd_ff *ff) { - /* The device discontinue to transfer packets. */ + amdtp_domain_stop(&ff->domain); + + // 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) -- Gitblit v1.6.2