Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b05dac5 authored by Dhananjay Kumar's avatar Dhananjay Kumar Committed by Banajit Goswami
Browse files

ASoC: msm: qdsp6v2: fix incomplete playback issue for non-gapless formats



Fix data loss on auto switching of playback to next clip
when current playback format is not having gapless support
in compressed driver.
Media playback complete event is sent to framework on completion
of partial drain, this is supposed to be before actual renderer
EOS by duration equal to value of PARTIAL_DRAIN_ACK_EARLY_BY_MSEC,
but due to uninitialized frame size for non-gapless formats this
duration calculated is inaccurate and sometimes triggers drain
completion too early, leading to premature teardown of playback
session.
Fix this by disabling gapless on formats not having valid gapless
parameters.
Recalculate partial drain delay based on flac min block size
to avoid incorrect drain delay for FLAC format.

Change-Id: I7f70a6fc17cc9c339ea754fd21aae6865355bef2
Signed-off-by: default avatarDhananjay Kumar <dhakumar@codeaurora.org>
Signed-off-by: default avatarBanajit Goswami <bgoswami@codeaurora.org>
parent 614080bf
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -604,6 +604,19 @@ static void compr_event_handler(uint32_t opcode,
	}
}

static int msm_compr_get_partial_drain_delay(int frame_sz, int sample_rate)
{
	int delay_time_ms = 0;

	delay_time_ms = ((DSP_NUM_OUTPUT_FRAME_BUFFERED * frame_sz * 1000) /
			sample_rate) + DSP_PP_BUFFERING_IN_MSEC;
	delay_time_ms = delay_time_ms > PARTIAL_DRAIN_ACK_EARLY_BY_MSEC ?
			delay_time_ms - PARTIAL_DRAIN_ACK_EARLY_BY_MSEC : 0;

	pr_debug("%s: partial drain delay %d\n", __func__, delay_time_ms);
	return delay_time_ms;
}

static void populate_codec_list(struct msm_compr_audio *prtd)
{
	pr_debug("%s\n", __func__);
@@ -1225,8 +1238,9 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
{
	struct snd_compr_runtime *runtime = cstream->runtime;
	struct msm_compr_audio *prtd = runtime->private_data;
	int ret = 0, frame_sz = 0, delay_time_ms = 0;
	int ret = 0, frame_sz = 0;
	int i, num_rates;
	bool is_format_gapless = false;

	pr_debug("%s\n", __func__);

@@ -1265,6 +1279,7 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
		pr_debug("SND_AUDIOCODEC_MP3\n");
		prtd->codec = FORMAT_MP3;
		frame_sz = MP3_OUTPUT_FRAME_SZ;
		is_format_gapless = true;
		break;
	}

@@ -1272,6 +1287,7 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
		pr_debug("SND_AUDIOCODEC_AAC\n");
		prtd->codec = FORMAT_MPEG4_AAC;
		frame_sz = AAC_OUTPUT_FRAME_SZ;
		is_format_gapless = true;
		break;
	}

@@ -1279,6 +1295,7 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
		pr_debug("SND_AUDIOCODEC_AC3\n");
		prtd->codec = FORMAT_AC3;
		frame_sz = AC3_OUTPUT_FRAME_SZ;
		is_format_gapless = true;
		break;
	}

@@ -1286,6 +1303,7 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
		pr_debug("SND_AUDIOCODEC_EAC3\n");
		prtd->codec = FORMAT_EAC3;
		frame_sz = EAC3_OUTPUT_FRAME_SZ;
		is_format_gapless = true;
		break;
	}

@@ -1310,6 +1328,13 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
	case SND_AUDIOCODEC_FLAC: {
		pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
		prtd->codec = FORMAT_FLAC;
		/*
		 * DSP bufferring is based on blk size,
		 * consider mininum buffering to rule out any false wait
		 */
		frame_sz =
			prtd->codec_param.codec.options.flac_dec.min_blk_size;
		is_format_gapless = true;
		break;
	}

@@ -1336,11 +1361,11 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
		return -EINVAL;
	}

	delay_time_ms = ((DSP_NUM_OUTPUT_FRAME_BUFFERED * frame_sz * 1000) /
			prtd->sample_rate) + DSP_PP_BUFFERING_IN_MSEC;
	delay_time_ms = delay_time_ms > PARTIAL_DRAIN_ACK_EARLY_BY_MSEC ?
			delay_time_ms - PARTIAL_DRAIN_ACK_EARLY_BY_MSEC : 0;
	prtd->partial_drain_delay = delay_time_ms;
	if (!is_format_gapless)
		prtd->gapless_state.use_dsp_gapless_mode = false;

	prtd->partial_drain_delay =
		msm_compr_get_partial_drain_delay(frame_sz, prtd->sample_rate);

	memcpy(&prtd->codec_param, params, sizeof(struct snd_compr_params));

@@ -2168,6 +2193,9 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
		if (ret < 0)
			pr_err("%s: CMD Format block failed ret %d\n",
				__func__, ret);

		prtd->partial_drain_delay = msm_compr_get_partial_drain_delay(
				flac_cfg.min_blk_size, prtd->sample_rate);
	}
	return 0;
}