From patchwork Tue May 13 14:27:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 4168111 X-Patchwork-Delegate: tiwai@suse.de Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 90505BFF02 for ; Tue, 13 May 2014 14:37:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7812720158 for ; Tue, 13 May 2014 14:37:04 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 158662010B for ; Tue, 13 May 2014 14:37:03 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 26660265750; Tue, 13 May 2014 16:37:02 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 09762265566; Tue, 13 May 2014 16:30:08 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 79CDA26556A; Tue, 13 May 2014 16:30:06 +0200 (CEST) Received: from smtp303.phy.lolipop.jp (smtp303.phy.lolipop.jp [210.157.22.87]) by alsa0.perex.cz (Postfix) with ESMTP id DFE68265520 for ; Tue, 13 May 2014 16:28:15 +0200 (CEST) Received: from smtp303.phy.lolipop.lan (HELO smtp303.phy.lolipop.jp) (172.17.1.87) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp303.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Tue, 13 May 2014 23:28:14 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp303.phy.lolipop.jp (LOLIPOP-Fsecure); Tue, 13 May 2014 23:27:53 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de Date: Tue, 13 May 2014 23:27:46 +0900 Message-Id: <1399991272-5807-10-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1399991272-5807-1-git-send-email-o-takashi@sakamocchi.jp> References: <1399991272-5807-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, stefanr@s5r6.in-berlin.de, fenlason@redhat.com, ffado-devel@lists.sf.net, linux1394-devel@lists.sourceforge.net Subject: [alsa-devel] [PATCH 09/15] oxfw: Change the way to start stream X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP In past commit, this driver can keep stream formations for each sampling rate. So its stream functionality can decide stream formations when given some parameters. This commit moves related codes from PCM functionality to stream functionality. Signed-off-by: Takashi Sakamoto --- sound/firewire/oxfw/oxfw.h | 3 +- sound/firewire/oxfw/oxfw_pcm.c | 38 +++------------ sound/firewire/oxfw/oxfw_stream.c | 99 ++++++++++++++++++++++++++++++++++----- 3 files changed, 96 insertions(+), 44 deletions(-) diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index 5d14424..e845581 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -60,7 +60,8 @@ struct snd_oxfw { }; int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw); -int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw); +int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, unsigned int rate, + unsigned int pcm_channels); void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw); void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw); void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw); diff --git a/sound/firewire/oxfw/oxfw_pcm.c b/sound/firewire/oxfw/oxfw_pcm.c index 75c0520..8f65e10 100644 --- a/sound/firewire/oxfw/oxfw_pcm.c +++ b/sound/firewire/oxfw/oxfw_pcm.c @@ -170,36 +170,10 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_oxfw *oxfw = substream->private_data; - int err; - - snd_oxfw_stream_stop_simplex(oxfw); - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - goto error; - - amdtp_stream_set_parameters(&oxfw->rx_stream, - params_rate(hw_params), - params_channels(hw_params), - 0); - amdtp_stream_set_pcm_format(&oxfw->rx_stream, - params_format(hw_params)); - - err = avc_general_set_sig_fmt(oxfw->unit, params_rate(hw_params), - AVC_GENERAL_PLUG_DIR_IN, 0); - if (err < 0) { - dev_err(&oxfw->unit->device, "failed to set sample rate\n"); - goto err_buffer; - } - - return 0; - -err_buffer: - snd_pcm_lib_free_vmalloc_buffer(substream); -error: - return err; + amdtp_stream_set_pcm_format(&oxfw->rx_stream, params_format(hw_params)); + return snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); } static int pcm_hw_free(struct snd_pcm_substream *substream) @@ -214,11 +188,11 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) static int pcm_prepare(struct snd_pcm_substream *substream) { struct snd_oxfw *oxfw = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; int err; - snd_oxfw_stream_stop_simplex(oxfw); - - err = snd_oxfw_stream_start_simplex(oxfw); + err = snd_oxfw_stream_start_simplex(oxfw, runtime->rate, + runtime->channels); if (err < 0) goto end; diff --git a/sound/firewire/oxfw/oxfw_stream.c b/sound/firewire/oxfw/oxfw_stream.c index 954584e..2d09df8 100644 --- a/sound/firewire/oxfw/oxfw_stream.c +++ b/sound/firewire/oxfw/oxfw_stream.c @@ -8,6 +8,8 @@ #include "oxfw.h" +#define CALLBACK_TIMEOUT 200 + /* * According to their datasheet: * OXFW970: 32.0/44.1/48.0/96.0 Khz, 8 audio channels I/O @@ -48,29 +50,104 @@ static int stop_stream(struct snd_oxfw *oxfw) cmp_connection_break(&oxfw->in_conn); } -int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw) +static int start_stream(struct snd_oxfw *oxfw, unsigned int rate, + unsigned int pcm_channels) { - int err = 0; + struct snd_oxfw_stream_formation *formations; + unsigned int i, midi_ports; + struct amdtp_stream *stream; + struct cmp_connection *conn; + int err; - mutex_lock(&oxfw->mutex); + stream = &oxfw->rx_stream; + formations = oxfw->rx_stream_formations; + conn = &oxfw->in_conn; + + /* Get stream formation */ + for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { + if (formations[i].rate != rate) + continue; + if ((pcm_channels == 0) || + (formations[i].pcm == pcm_channels)) + break; + } + if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) { + err = -EINVAL; + goto end; + } - if (amdtp_streaming_error(&oxfw->rx_stream)) - stop_stream(oxfw); + pcm_channels = formations[i].pcm; + midi_ports = formations[i].midi; - if (amdtp_stream_running(&oxfw->rx_stream)) + /* The stream should have one pcm channels at least */ + if (pcm_channels == 0) { + err = -EINVAL; goto end; + } + amdtp_stream_set_parameters(stream, rate, pcm_channels, midi_ports); - err = cmp_connection_establish(&oxfw->in_conn, - amdtp_stream_get_max_payload(&oxfw->rx_stream)); + /* Establish connection */ + err = cmp_connection_establish(conn, + amdtp_stream_get_max_payload(stream)); if (err < 0) goto end; - err = amdtp_stream_start(&oxfw->rx_stream, - oxfw->in_conn.resources.channel, - oxfw->in_conn.speed); + /* Start stream */ + err = amdtp_stream_start(stream, + conn->resources.channel, + conn->speed); + if (err < 0) { + cmp_connection_break(conn); + goto end; + } + + /* Wait first callback */ + err = amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT); if (err < 0) stop_stream(oxfw); end: + return err; +} + +int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, unsigned int rate, + unsigned int pcm_channels) +{ + unsigned int curr_rate; + int err = 0; + + mutex_lock(&oxfw->mutex); + + /* packet queueing error */ + if (amdtp_streaming_error(&oxfw->rx_stream)) + stop_stream(oxfw); + + /* arrange sampling rate */ + err = avc_general_get_sig_fmt(oxfw->unit, &curr_rate, + AVC_GENERAL_PLUG_DIR_IN, 0); + if (err < 0) { + dev_err(&oxfw->unit->device, + "fail to get sampling rate: %d\n", err); + goto end; + } + if (curr_rate != rate) { + stop_stream(oxfw); + + err = avc_general_set_sig_fmt(oxfw->unit, rate, + AVC_GENERAL_PLUG_DIR_IN, 0); + if (err < 0) { + dev_err(&oxfw->unit->device, + "fail to set sampling rate: %d\n", err); + goto end; + } + } + + if (!amdtp_stream_running(&oxfw->rx_stream)) { + err = start_stream(oxfw, rate, pcm_channels); + if (err < 0) + dev_err(&oxfw->unit->device, + "fail to start stream: %d\n", err); + } +end: mutex_unlock(&oxfw->mutex); return err; }