Commit 3d725066 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai
Browse files

ALSA: fireworks: configure sampling transfer frequency in pcm.hw_params callback



This commit is a part of preparation to perform allocation/release
of isochronous resources in pcm.hw_params/hw_free callbacks.

At present, several operations are done in pcm.prepare callback. To
reduce load of the callback, This commit splits out an operation to
set sampling transfer frequency in pcm.hw_params callback.

Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent fb56eb73
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -206,7 +206,8 @@ int snd_efw_command_get_sampling_rate(struct snd_efw *efw, unsigned int *rate);
int snd_efw_command_set_sampling_rate(struct snd_efw *efw, unsigned int rate);

int snd_efw_stream_init_duplex(struct snd_efw *efw);
int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate);
int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate);
int snd_efw_stream_start_duplex(struct snd_efw *efw);
void snd_efw_stream_stop_duplex(struct snd_efw *efw);
void snd_efw_stream_update_duplex(struct snd_efw *efw);
void snd_efw_stream_destroy_duplex(struct snd_efw *efw);
+5 −2
Original line number Diff line number Diff line
@@ -18,8 +18,11 @@ static int midi_open(struct snd_rawmidi_substream *substream)
		goto end;

	mutex_lock(&efw->mutex);
	err = snd_efw_stream_reserve_duplex(efw, 0);
	if (err >= 0) {
		++efw->substreams_counter;
	err = snd_efw_stream_start_duplex(efw, 0);
		err = snd_efw_stream_start_duplex(efw);
	}
	mutex_unlock(&efw->mutex);
	if (err < 0)
		snd_efw_stream_lock_release(efw);
+8 −6
Original line number Diff line number Diff line
@@ -231,12 +231,16 @@ static int pcm_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(&efw->mutex);
		err = snd_efw_stream_reserve_duplex(efw, rate);
		if (err >= 0)
			++efw->substreams_counter;
		mutex_unlock(&efw->mutex);
	}

	return 0;
	return err;
}

static int pcm_hw_free(struct snd_pcm_substream *substream)
@@ -257,10 +261,9 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
static int pcm_capture_prepare(struct snd_pcm_substream *substream)
{
	struct snd_efw *efw = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	int err;

	err = snd_efw_stream_start_duplex(efw, runtime->rate);
	err = snd_efw_stream_start_duplex(efw);
	if (err >= 0)
		amdtp_stream_pcm_prepare(&efw->tx_stream);

@@ -269,10 +272,9 @@ static int pcm_capture_prepare(struct snd_pcm_substream *substream)
static int pcm_playback_prepare(struct snd_pcm_substream *substream)
{
	struct snd_efw *efw = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	int err;

	err = snd_efw_stream_start_duplex(efw, runtime->rate);
	err = snd_efw_stream_start_duplex(efw);
	if (err >= 0)
		amdtp_stream_pcm_prepare(&efw->rx_stream);

+42 −23
Original line number Diff line number Diff line
@@ -189,47 +189,63 @@ end:
	return err;
}

int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate)
int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate)
{
	unsigned int curr_rate;
	int err = 0;

	// Need no substreams.
	if (efw->substreams_counter == 0)
		return -EIO;
	int err;

	/*
	 * Considering JACK/FFADO streaming:
	 * TODO: This can be removed hwdep functionality becomes popular.
	 */
	// Considering JACK/FFADO streaming:
	// TODO: This can be removed hwdep functionality becomes popular.
	err = check_connection_used_by_others(efw, &efw->rx_stream);
	if (err < 0)
		goto end;
		return err;

	/* stop streams if rate is different */
	// stop streams if rate is different.
	err = snd_efw_command_get_sampling_rate(efw, &curr_rate);
	if (err < 0)
		goto end;
		return err;
	if (rate == 0)
		rate = curr_rate;
	if (rate != curr_rate ||
	    amdtp_streaming_error(&efw->tx_stream) ||
	    amdtp_streaming_error(&efw->rx_stream)) {
	if (rate != curr_rate) {
		stop_stream(efw, &efw->tx_stream);
		stop_stream(efw, &efw->rx_stream);
	}

	/* master should be always running */
	if (!amdtp_stream_running(&efw->rx_stream)) {
	if (efw->substreams_counter == 0 || rate != curr_rate) {
		err = snd_efw_command_set_sampling_rate(efw, rate);
		if (err < 0)
			goto end;
			return err;
	}

	return 0;
}

int snd_efw_stream_start_duplex(struct snd_efw *efw)
{
	unsigned int rate;
	int err = 0;

	// Need no substreams.
	if (efw->substreams_counter == 0)
		return -EIO;

	err = snd_efw_command_get_sampling_rate(efw, &rate);
	if (err < 0)
		return err;

	if (amdtp_streaming_error(&efw->rx_stream) ||
	    amdtp_streaming_error(&efw->tx_stream)) {
		stop_stream(efw, &efw->rx_stream);
		stop_stream(efw, &efw->tx_stream);
	}

	/* master should be always running */
	if (!amdtp_stream_running(&efw->rx_stream)) {
		err = start_stream(efw, &efw->rx_stream, rate);
		if (err < 0) {
			dev_err(&efw->unit->device,
				"fail to start AMDTP master stream:%d\n", err);
			goto end;
			goto error;
		}
	}

@@ -238,11 +254,14 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate)
		if (err < 0) {
			dev_err(&efw->unit->device,
				"fail to start AMDTP slave stream:%d\n", err);
			stop_stream(efw, &efw->tx_stream);
			stop_stream(efw, &efw->rx_stream);
			goto error;
		}
	}
end:

	return 0;
error:
	stop_stream(efw, &efw->rx_stream);
	stop_stream(efw, &efw->tx_stream);
	return err;
}