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

Commit 246f05b5 authored by Alexy Joseph's avatar Alexy Joseph
Browse files

ASoC: msm: qdsp6v2: Handle additional codec specific metadata



Codec specific  metadata is sent only for first stream in gapless
playback. This causes incorrect configuration to be set for second
stream and distortions are observed due to framedrops in adsp.
Add support to send codec specific format during start of
next stream in gapless.
Add bit rate to wma codec data structure as it can vary between
streams in gapless.

Change-Id: I39f34ea1addff720612fe3e06257e7d75889e574
Signed-off-by: default avatarChaithanya Krishna Bacharaju <chaithan@codeaurora.org>
Signed-off-by: default avatarAlexy Joseph <alexyj@codeaurora.org>
parent 1db12269
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ struct snd_enc_wma {
	__u32 encodeopt;
	__u32 encodeopt1;
	__u32 encodeopt2;
	__u32 avg_bit_rate;
};


+116 −122
Original line number Diff line number Diff line
@@ -95,10 +95,9 @@ struct msm_compr_gapless_state {
	int32_t stream_opened[MAX_NUMBER_OF_STREAMS];
	uint32_t initial_samples_drop;
	uint32_t trailing_samples_drop;
	uint32_t min_blk_size;
	uint32_t max_blk_size;
	uint32_t gapless_transition;
	bool use_dsp_gapless_mode;
	union snd_codec_options codec_options;
};

static unsigned int supported_sample_rates[] = {
@@ -642,7 +641,8 @@ static void populate_codec_list(struct msm_compr_audio *prtd)
}

static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
					     int stream_id)
					     int stream_id,
					     bool use_gapless_codec_options)
{
	struct snd_compr_runtime *runtime = cstream->runtime;
	struct msm_compr_audio *prtd = runtime->private_data;
@@ -656,13 +656,26 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
	struct asm_vorbis_cfg vorbis_cfg;
	struct asm_alac_cfg alac_cfg;
	struct asm_ape_cfg ape_cfg;
	union snd_codec_options *codec_options;

	u32 cfg;
	int ret = 0;
	uint16_t bit_width = 16;
	bool use_default_chmap = true;
	char *chmap = NULL;

	pr_debug("%s: use_gapless_codec_options %d\n",
			__func__, use_gapless_codec_options);

	if (use_gapless_codec_options)
		codec_options = &(prtd->gapless_state.codec_options);
	else
		codec_options = &(prtd->codec_param.codec.options);

	if (!codec_options) {
		pr_err("%s: codec_options is NULL\n", __func__);
		return -EINVAL;
	}

	switch (prtd->codec) {
	case FORMAT_LINEAR_PCM:
		pr_debug("SND_AUDIOCODEC_PCM\n");
@@ -717,16 +730,12 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
		wma_cfg.format_tag = prtd->codec_param.codec.format;
		wma_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
		wma_cfg.sample_rate = prtd->sample_rate;
		wma_cfg.avg_bytes_per_sec =
			prtd->codec_param.codec.bit_rate/8;
		wma_cfg.block_align =
			prtd->codec_param.codec.options.wma.super_block_align;
		wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
		wma_cfg.block_align = codec_options->wma.super_block_align;
		wma_cfg.valid_bits_per_sample =
		prtd->codec_param.codec.options.wma.bits_per_sample;
		wma_cfg.ch_mask =
			prtd->codec_param.codec.options.wma.channelmask;
		wma_cfg.encode_opt =
			prtd->codec_param.codec.options.wma.encodeopt;
			codec_options->wma.bits_per_sample;
		wma_cfg.ch_mask = codec_options->wma.channelmask;
		wma_cfg.encode_opt = codec_options->wma.encodeopt;
		ret = q6asm_media_format_block_wma(prtd->audio_client,
					&wma_cfg, stream_id);
		if (ret < 0)
@@ -737,22 +746,15 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
		memset(&wma_pro_cfg, 0x0, sizeof(struct asm_wmapro_cfg));
		wma_pro_cfg.format_tag = prtd->codec_param.codec.format;
		wma_pro_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
		wma_pro_cfg.sample_rate =
			prtd->sample_rate;
		wma_pro_cfg.avg_bytes_per_sec =
			prtd->codec_param.codec.bit_rate/8;
		wma_pro_cfg.block_align =
			prtd->codec_param.codec.options.wma.super_block_align;
		wma_pro_cfg.sample_rate = prtd->sample_rate;
		wma_cfg.avg_bytes_per_sec = codec_options->wma.avg_bit_rate/8;
		wma_pro_cfg.block_align = codec_options->wma.super_block_align;
		wma_pro_cfg.valid_bits_per_sample =
			prtd->codec_param.codec.options.wma.bits_per_sample;
		wma_pro_cfg.ch_mask =
			prtd->codec_param.codec.options.wma.channelmask;
		wma_pro_cfg.encode_opt =
			prtd->codec_param.codec.options.wma.encodeopt;
		wma_pro_cfg.adv_encode_opt =
			prtd->codec_param.codec.options.wma.encodeopt1;
		wma_pro_cfg.adv_encode_opt2 =
			prtd->codec_param.codec.options.wma.encodeopt2;
			codec_options->wma.bits_per_sample;
		wma_pro_cfg.ch_mask = codec_options->wma.channelmask;
		wma_pro_cfg.encode_opt = codec_options->wma.encodeopt;
		wma_pro_cfg.adv_encode_opt = codec_options->wma.encodeopt1;
		wma_pro_cfg.adv_encode_opt2 = codec_options->wma.encodeopt2;
		ret = q6asm_media_format_block_wmapro(prtd->audio_client,
				&wma_pro_cfg, stream_id);
		if (ret < 0)
@@ -767,16 +769,13 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
		flac_cfg.ch_cfg = prtd->num_channels;
		flac_cfg.sample_rate = prtd->sample_rate;
		flac_cfg.stream_info_present = 1;
		flac_cfg.sample_size =
			prtd->codec_param.codec.options.flac_dec.sample_size;
		flac_cfg.min_blk_size =
			prtd->codec_param.codec.options.flac_dec.min_blk_size;
		flac_cfg.max_blk_size =
			prtd->codec_param.codec.options.flac_dec.max_blk_size;
		flac_cfg.sample_size = codec_options->flac_dec.sample_size;
		flac_cfg.min_blk_size = codec_options->flac_dec.min_blk_size;
		flac_cfg.max_blk_size = codec_options->flac_dec.max_blk_size;
		flac_cfg.max_frame_size =
			prtd->codec_param.codec.options.flac_dec.max_frame_size;
			codec_options->flac_dec.max_frame_size;
		flac_cfg.min_frame_size =
			prtd->codec_param.codec.options.flac_dec.min_frame_size;
			codec_options->flac_dec.min_frame_size;

		ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
							&flac_cfg, stream_id);
@@ -788,8 +787,8 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
	case FORMAT_VORBIS:
		pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
		memset(&vorbis_cfg, 0x0, sizeof(struct asm_vorbis_cfg));
		cfg = prtd->codec_param.codec.options.vorbis_dec.bit_stream_fmt;
		vorbis_cfg.bit_stream_fmt = cfg;
		vorbis_cfg.bit_stream_fmt =
			codec_options->vorbis_dec.bit_stream_fmt;

		ret = q6asm_stream_media_format_block_vorbis(
					prtd->audio_client, &vorbis_cfg,
@@ -804,22 +803,18 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
		memset(&alac_cfg, 0x0, sizeof(struct asm_alac_cfg));
		alac_cfg.num_channels = prtd->num_channels;
		alac_cfg.sample_rate = prtd->sample_rate;
		alac_cfg.frame_length =
			prtd->codec_param.codec.options.alac.frame_length;
		alac_cfg.frame_length = codec_options->alac.frame_length;
		alac_cfg.compatible_version =
			prtd->codec_param.codec.options.alac.compatible_version;
		alac_cfg.bit_depth =
			prtd->codec_param.codec.options.alac.bit_depth;
		alac_cfg.pb = prtd->codec_param.codec.options.alac.pb;
		alac_cfg.mb = prtd->codec_param.codec.options.alac.mb;
		alac_cfg.kb = prtd->codec_param.codec.options.alac.kb;
		alac_cfg.max_run = prtd->codec_param.codec.options.alac.max_run;
		alac_cfg.max_frame_bytes =
			prtd->codec_param.codec.options.alac.max_frame_bytes;
		alac_cfg.avg_bit_rate =
			prtd->codec_param.codec.options.alac.avg_bit_rate;
			codec_options->alac.compatible_version;
		alac_cfg.bit_depth = codec_options->alac.bit_depth;
		alac_cfg.pb = codec_options->alac.pb;
		alac_cfg.mb = codec_options->alac.mb;
		alac_cfg.kb = codec_options->alac.kb;
		alac_cfg.max_run = codec_options->alac.max_run;
		alac_cfg.max_frame_bytes = codec_options->alac.max_frame_bytes;
		alac_cfg.avg_bit_rate = codec_options->alac.avg_bit_rate;
		alac_cfg.channel_layout_tag =
			prtd->codec_param.codec.options.alac.channel_layout_tag;
			codec_options->alac.channel_layout_tag;

		ret = q6asm_media_format_block_alac(prtd->audio_client,
							&alac_cfg, stream_id);
@@ -833,21 +828,17 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
		ape_cfg.num_channels = prtd->num_channels;
		ape_cfg.sample_rate = prtd->sample_rate;
		ape_cfg.compatible_version =
			prtd->codec_param.codec.options.ape.compatible_version;
			codec_options->ape.compatible_version;
		ape_cfg.compression_level =
			prtd->codec_param.codec.options.ape.compression_level;
		ape_cfg.format_flags =
			prtd->codec_param.codec.options.ape.format_flags;
		ape_cfg.blocks_per_frame =
			prtd->codec_param.codec.options.ape.blocks_per_frame;
			codec_options->ape.compression_level;
		ape_cfg.format_flags = codec_options->ape.format_flags;
		ape_cfg.blocks_per_frame = codec_options->ape.blocks_per_frame;
		ape_cfg.final_frame_blocks =
			prtd->codec_param.codec.options.ape.final_frame_blocks;
		ape_cfg.total_frames =
			prtd->codec_param.codec.options.ape.total_frames;
		ape_cfg.bits_per_sample =
			prtd->codec_param.codec.options.ape.bits_per_sample;
			codec_options->ape.final_frame_blocks;
		ape_cfg.total_frames = codec_options->ape.total_frames;
		ape_cfg.bits_per_sample = codec_options->ape.bits_per_sample;
		ape_cfg.seek_table_present =
			prtd->codec_param.codec.options.ape.seek_table_present;
			codec_options->ape.seek_table_present;

		ret = q6asm_media_format_block_ape(prtd->audio_client,
							&ape_cfg, stream_id);
@@ -1024,7 +1015,7 @@ static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)
	prtd->buffer_paddr = ac->port[dir].buf[0].phys;
	prtd->buffer_size  = runtime->fragments * runtime->fragment_size;

	ret = msm_compr_send_media_format_block(cstream, ac->stream_id);
	ret = msm_compr_send_media_format_block(cstream, ac->stream_id, false);
	if (ret < 0) {
		pr_err("%s, failed to send media format block\n", __func__);
	}
@@ -1095,8 +1086,6 @@ static int msm_compr_open(struct snd_compr_stream *cstream)
	prtd->partial_drain_delay = 0;
	prtd->next_stream = 0;
	memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
	prtd->gapless_state.min_blk_size = 65537;
	prtd->gapless_state.max_blk_size = 65537;
	/*
	 * Update the use_dsp_gapless_mode from gapless struture with the value
	 * part of platform data.
@@ -1673,8 +1662,6 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
			prtd->first_buffer = 1;
			prtd->last_buffer = 0;
			prtd->gapless_state.gapless_transition = 1;
			prtd->gapless_state.min_blk_size = 65537;
			prtd->gapless_state.max_blk_size = 65537;
			prtd->marker_timestamp = 0;

			/*
@@ -1851,7 +1838,8 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
				 __func__);
			break;
		}
		rc = msm_compr_send_media_format_block(cstream, stream_id);
		rc = msm_compr_send_media_format_block(cstream,
						stream_id, false);
		if (rc < 0) {
			pr_err("%s, failed to send media format block\n",
				__func__);
@@ -2124,8 +2112,6 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
{
	struct msm_compr_audio *prtd;
	struct audio_client *ac;
	struct asm_flac_cfg flac_cfg;
	int ret = 0;
	pr_debug("%s\n", __func__);

	if (!metadata || !cstream)
@@ -2149,49 +2135,56 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
	} else if (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY) {
		pr_debug("%s, got encoder delay %u", __func__, metadata->value[0]);
		prtd->gapless_state.initial_samples_drop = metadata->value[0];
	} else if (metadata->key == SNDRV_COMPRESS_MIN_BLK_SIZE) {
		pr_debug("%s, got min_blk_size %u",
			__func__, metadata->value[0]);
		prtd->gapless_state.min_blk_size = metadata->value[0];
	} else if (metadata->key == SNDRV_COMPRESS_MAX_BLK_SIZE) {
		pr_debug("%s, got max_blk_size %u",
			__func__, metadata->value[0]);
		prtd->gapless_state.max_blk_size = metadata->value[0];
	}

	if ((prtd->codec == FORMAT_FLAC) &&
	    (prtd->gapless_state.min_blk_size >= 0) &&
	    (prtd->gapless_state.min_blk_size <= FLAC_BLK_SIZE_LIMIT) &&
	    (prtd->gapless_state.max_blk_size >= 0) &&
	    (prtd->gapless_state.max_blk_size <= FLAC_BLK_SIZE_LIMIT)) {
		pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
		memset(&flac_cfg, 0x0, sizeof(struct asm_flac_cfg));
		flac_cfg.ch_cfg = prtd->num_channels;
		flac_cfg.sample_rate = prtd->sample_rate;
		flac_cfg.stream_info_present = 1;
		flac_cfg.sample_size =
			prtd->codec_param.codec.options.flac_dec.sample_size;
		flac_cfg.min_blk_size =
			prtd->gapless_state.min_blk_size;
		flac_cfg.max_blk_size =
			prtd->gapless_state.max_blk_size;
		flac_cfg.max_frame_size =
			prtd->codec_param.codec.options.flac_dec.max_frame_size;
		flac_cfg.min_frame_size =
			prtd->codec_param.codec.options.flac_dec.min_frame_size;
		pr_debug("%s: min_blk_size %d max_blk_size %d\n",
			__func__, flac_cfg.min_blk_size, flac_cfg.max_blk_size);
	}

		ret = q6asm_stream_media_format_block_flac(ac, &flac_cfg,
								ac->stream_id);
		if (ret < 0)
			pr_err("%s: CMD Format block failed ret %d\n",
				__func__, ret);
	return 0;
}

static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream,
				union snd_codec_options *codec_options)
{
	struct msm_compr_audio *prtd;
	struct audio_client *ac;
	int ret = 0;

		prtd->partial_drain_delay = msm_compr_get_partial_drain_delay(
				flac_cfg.min_blk_size, prtd->sample_rate);
	if (!codec_options || !cstream)
		return -EINVAL;

	prtd = cstream->runtime->private_data;
	if (!prtd || !prtd->audio_client) {
		pr_err("%s: prtd or audio client is NULL\n", __func__);
		return -EINVAL;
	}
	return 0;

	ac = prtd->audio_client;

	pr_debug("%s: got codec options for codec type %u",
		__func__, prtd->codec);
	switch (prtd->codec) {
	case FORMAT_WMA_V9:
	case FORMAT_WMA_V10PRO:
	case FORMAT_FLAC:
	case FORMAT_VORBIS:
	case FORMAT_ALAC:
	case FORMAT_APE:
		memcpy(&(prtd->gapless_state.codec_options),
			codec_options,
			sizeof(union snd_codec_options));
		ret = msm_compr_send_media_format_block(cstream,
						ac->stream_id, true);
		if (ret < 0) {
			pr_err("%s: failed to send media format block\n",
				__func__);
		}
		break;

	default:
		pr_debug("%s: Ignore sending CMD Format block\n",
			__func__);
		break;
	}

	return ret;
}

static int msm_compr_volume_put(struct snd_kcontrol *kcontrol,
@@ -3178,6 +3171,7 @@ static struct snd_compr_ops msm_compr_ops = {
	.pointer		= msm_compr_pointer,
	.set_params		= msm_compr_set_params,
	.set_metadata		= msm_compr_set_metadata,
	.set_next_track_param	= msm_compr_set_next_track_param,
	.ack			= msm_compr_ack,
	.copy			= msm_compr_copy,
	.get_caps		= msm_compr_get_caps,