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

Commit 57ff2ed1 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm: qdsp6v2: Fix offload gapless transition"

parents 6aa9bdf5 f2bbf326
Loading
Loading
Loading
Loading
+66 −14
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@
#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
#define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
#define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
#define COMPR_PLAYBACK_DSP_FRAGMENT_SIZE (32 * 1024)

#define COMPRESSED_LR_VOL_MAX_STEPS	0x2000
const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0,
@@ -172,6 +173,11 @@ struct msm_compr_audio {
	wait_queue_head_t close_wait;
	wait_queue_head_t wait_for_stream_avail;

	uint32_t dsp_fragment_size;
	uint32_t dsp_fragments;
	uint32_t dsp_fragment_ratio;
	uint32_t dsp_fragments_sent;

	spinlock_t lock;
};

@@ -328,10 +334,22 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
				prtd->gapless_state.initial_samples_drop,
				prtd->gapless_state.trailing_samples_drop);

	buffer_length = prtd->codec_param.buffer.fragment_size;
	bytes_available = prtd->bytes_received - prtd->copied_total;
	if (bytes_available < prtd->codec_param.buffer.fragment_size)


	if (bytes_available < prtd->dsp_fragment_size)
		buffer_length = bytes_available;
	else if (bytes_available > prtd->cstream->runtime->fragment_size)
		buffer_length = prtd->cstream->runtime->fragment_size;
	else {
		/*
		 * do_div divides in place and bytes_available is modified
		 * to the quotient after the division. Essentially, write
		 * the remaining data in dsp_fragment_size'd chunks
		 */
		do_div(bytes_available, prtd->dsp_fragment_size);
		buffer_length = bytes_available * prtd->dsp_fragment_size;
	}

	if (prtd->byte_offset + buffer_length > prtd->buffer_size) {
		buffer_length = (prtd->buffer_size - prtd->byte_offset);
@@ -419,7 +437,11 @@ static void compr_event_handler(uint32_t opcode,
		if (prtd->byte_offset >= prtd->buffer_size)
			prtd->byte_offset -= prtd->buffer_size;

		prtd->dsp_fragments_sent += token / prtd->dsp_fragment_size;
		if (prtd->dsp_fragments_sent >= prtd->dsp_fragment_ratio) {
			snd_compr_fragment_elapsed(cstream);
			prtd->dsp_fragments_sent = 0;
		}

		if (!atomic_read(&prtd->start)) {
			/* Writes must be restarted from _copy() */
@@ -430,7 +452,7 @@ static void compr_event_handler(uint32_t opcode,
		}

		bytes_available = prtd->bytes_received - prtd->copied_total;
		if (bytes_available < cstream->runtime->fragment_size) {
		if (bytes_available < prtd->dsp_fragment_size) {
			pr_debug("WRITE_DONE Insufficient data to send. break out\n");
			atomic_set(&prtd->xrun, 1);

@@ -442,7 +464,7 @@ static void compr_event_handler(uint32_t opcode,
				wake_up(&prtd->drain_wait);
				atomic_set(&prtd->drain, 0);
			}
		} else if ((bytes_available == cstream->runtime->fragment_size)
		} else if ((bytes_available == prtd->dsp_fragment_size)
				 && atomic_read(&prtd->drain)) {
			prtd->last_buffer = 1;
			msm_compr_send_buffer(prtd);
@@ -507,7 +529,7 @@ static void compr_event_handler(uint32_t opcode,
			spin_lock_irqsave(&prtd->lock, flags);
			if (!prtd->bytes_sent) {
				bytes_available = prtd->bytes_received - prtd->copied_total;
				if (bytes_available < cstream->runtime->fragment_size) {
				if (bytes_available < prtd->dsp_fragment_size) {
					pr_debug("CMD_RUN_V2 Insufficient data to send. break out\n");
					atomic_set(&prtd->xrun, 1);
				} else
@@ -1041,12 +1063,38 @@ static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)

	runtime->fragments = prtd->codec_param.buffer.fragments;
	runtime->fragment_size = prtd->codec_param.buffer.fragment_size;

	/* use smaller DSP fragments to ease gapless transition by reducing the
	 * minimum amount of data necessary to start DSP decoding
	 */
	if (runtime->fragment_size < COMPR_PLAYBACK_DSP_FRAGMENT_SIZE) {
		prtd->dsp_fragment_size = runtime->fragment_size;
	} else if ((runtime->fragment_size %
			COMPR_PLAYBACK_DSP_FRAGMENT_SIZE) != 0) {
		prtd->dsp_fragment_size = runtime->fragment_size;
		pr_debug("%s: runtime fragment size %d is not a multiple of %d\n",
				__func__, runtime->fragment_size,
				COMPR_PLAYBACK_DSP_FRAGMENT_SIZE);
	} else {
		prtd->dsp_fragment_size = COMPR_PLAYBACK_DSP_FRAGMENT_SIZE;
	}
	prtd->dsp_fragment_ratio = runtime->fragment_size /
					prtd->dsp_fragment_size;
	prtd->dsp_fragments = runtime->fragments *
					prtd->dsp_fragment_ratio;

	if (prtd->dsp_fragments > COMPR_PLAYBACK_MAX_NUM_FRAGMENTS) {
		pr_err("%s: Invalid fragment count: %d", __func__,
				prtd->dsp_fragments);
		return -EINVAL;
	}

	pr_debug("allocate %d buffers each of size %d\n",
			runtime->fragments,
			runtime->fragment_size);
	ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
					runtime->fragment_size,
					runtime->fragments);
			prtd->dsp_fragment_size,
			prtd->dsp_fragments);
	if (ret < 0) {
		pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
		return -ENOMEM;
@@ -1057,6 +1105,7 @@ static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)
	prtd->app_pointer  = 0;
	prtd->bytes_received = 0;
	prtd->bytes_sent = 0;
	prtd->dsp_fragments_sent = 0;
	prtd->buffer       = ac->port[dir].buf[0].data;
	prtd->buffer_paddr = ac->port[dir].buf[0].phys;
	prtd->buffer_size  = runtime->fragments * runtime->fragment_size;
@@ -1601,6 +1650,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
		prtd->bytes_received = 0;
		prtd->bytes_sent = 0;
		prtd->marker_timestamp = 0;
		prtd->dsp_fragments_sent = 0;

		atomic_set(&prtd->xrun, 0);
		spin_unlock_irqrestore(&prtd->lock, flags);
@@ -1661,8 +1711,8 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
			 */
			bytes_to_write = prtd->bytes_received
						- prtd->copied_total;
			WARN(bytes_to_write > runtime->fragment_size,
			     "last write %d cannot be > than fragment_size",
			WARN(bytes_to_write > prtd->dsp_fragment_size,
			     "last write %d cannot be > than dsp_fragment_size",
			     bytes_to_write);

			if (bytes_to_write > 0) {
@@ -1742,7 +1792,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
			if (atomic_read(&prtd->eos))
				prtd->gapless_state.gapless_transition = 1;
			prtd->marker_timestamp = 0;

			prtd->dsp_fragments_sent = 0;
			/*
			Don't reset these as these vars map to
			total_bytes_transferred and total_bytes_available
@@ -1836,6 +1886,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
			prtd->app_pointer  = 0;
			prtd->first_buffer = 1;
			prtd->last_buffer = 0;
			prtd->dsp_fragments_sent = 0;
			atomic_set(&prtd->drain, 0);
			atomic_set(&prtd->xrun, 1);
			spin_unlock_irqrestore(&prtd->lock, flags);
@@ -2106,7 +2157,8 @@ static int msm_compr_copy(struct snd_compr_stream *cstream,

	/*
	 * If stream is started and there has been an xrun,
	 * since the available bytes fits fragment_size, copy the data right away
	 * since the available bytes fits dsp_fragment_size,
	 * copy the data right away
	 */
	spin_lock_irqsave(&prtd->lock, flags);
	prtd->bytes_received += count;
@@ -2114,7 +2166,7 @@ static int msm_compr_copy(struct snd_compr_stream *cstream,
		if (atomic_read(&prtd->xrun)) {
			pr_debug("%s: in xrun, count = %zd\n", __func__, count);
			bytes_available = prtd->bytes_received - prtd->copied_total;
			if (bytes_available >= runtime->fragment_size) {
			if (bytes_available >= prtd->dsp_fragment_size) {
				pr_debug("%s: handle xrun, bytes_to_write = %llu\n",
					 __func__,
					 bytes_available);