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

Commit 9fc48ad5 authored by Manish Dewangan's avatar Manish Dewangan
Browse files

ASoC: msm: qdspv2: add support for MULTI_CHANNEL_PCM_V3 command



Driver changes to use ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 command.
This command supports playback/record of both 32 bit
(24 bit data in 32 bit word) and 24 bit packed. Update platform
drivers to this for SNDRV_PCM_FORMAT_S24_LE record and playback.

CRs-Fixed: 1011048
Change-Id: I6f98bf3402a737bc21daff33b13b137850a690ea
Signed-off-by: default avatarManish Dewangan <manish@codeaurora.org>
parent 50239ba4
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -3341,6 +3341,16 @@ struct asm_multi_channel_pcm_fmt_blk_v3 {
 */
} __packed;

/*
 * Payload of the multichannel PCM configuration parameters in
 * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 media format.
 */
struct asm_multi_channel_pcm_fmt_blk_param_v3 {
	struct apr_hdr hdr;
	struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
	struct asm_multi_channel_pcm_fmt_blk_v3 param;
} __packed;

struct asm_stream_cmd_set_encdec_param {
	u32                  param_id;
	/* ID of the parameter. */
@@ -3376,6 +3386,66 @@ struct asm_dec_ddp_endp_param_v2 {
	int endp_param_value;
} __packed;


/*
 * Payload of the multichannel PCM encoder configuration parameters in
 * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 media format.
 */

struct asm_multi_channel_pcm_enc_cfg_v3 {
	struct apr_hdr hdr;
	struct asm_stream_cmd_set_encdec_param encdec;
	struct asm_enc_cfg_blk_param_v2 encblk;
	uint16_t num_channels;
	/*
	 * Number of PCM channels.
	 * @values
	 * - 0 -- Native mode
	 * - 1 -- 8 channels
	 * Native mode indicates that encoding must be performed with the number
	 * of channels at the input.
	 */
	uint16_t  bits_per_sample;
	/*
	 * Number of bits per sample per channel.
	 * @values 16, 24
	 */
	uint32_t  sample_rate;
	/*
	 * Number of samples per second.
	 * @values 0, 8000 to 48000 Hz
	 * A value of 0 indicates the native sampling rate. Encoding is
	 * performed at the input sampling rate.
	 */
	uint16_t  is_signed;
	/*
	 * Flag that indicates the PCM samples are signed (1). Currently, only
	 * signed PCM samples are supported.
	 */
	uint16_t    sample_word_size;
	/*
	 * The size in bits of the word that holds a sample of a channel.
	 * @values 16, 24, 32
	 * 16-bit samples are always placed in 16-bit words:
	 * sample_word_size = 1.
	 * 24-bit samples can be placed in 32-bit words or in consecutive
	 * 24-bit words.
	 * - If sample_word_size = 32, 24-bit samples are placed in the
	 * most significant 24 bits of a 32-bit word.
	 * - If sample_word_size = 24, 24-bit samples are placed in
	 * 24-bit words. @tablebulletend
	 */
	uint8_t   channel_mapping[8];
	/*
	 * Channel mapping array expected at the encoder output.
	 *  Channel[i] mapping describes channel i inside the buffer, where
	 *  0 @le i < num_channels. All valid used channels must be present at
	 *  the beginning of the array.
	 * If Native mode is set for the channels, this field is ignored.
	 * @values See Section @xref{dox:PcmChannelDefs}
	 */
};

/* @brief Multichannel PCM encoder configuration structure used
 * in the #ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2 command.
 */
+39 −2
Original line number Diff line number Diff line
@@ -240,6 +240,9 @@ int q6asm_open_read(struct audio_client *ac, uint32_t format
int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample);

int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
		       uint16_t bits_per_sample);

int q6asm_open_write(struct audio_client *ac, uint32_t format
		/*, uint16_t bits_per_sample*/);

@@ -249,10 +252,17 @@ int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
int q6asm_open_shared_io(struct audio_client *ac,
			 struct shared_io_config *c, int dir);

int q6asm_open_write_v3(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample);

int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
			       uint16_t bits_per_sample, int32_t stream_id,
			       bool is_gapless_mode);

int q6asm_stream_open_write_v3(struct audio_client *ac, uint32_t format,
			       uint16_t bits_per_sample, int32_t stream_id,
			       bool is_gapless_mode);

int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
				uint32_t passthrough_flag);

@@ -349,10 +359,21 @@ int q6asm_enc_cfg_blk_pcm_v2(struct audio_client *ac,
			bool use_default_chmap, bool use_back_flavor,
			u8 *channel_map);

int q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
			     uint32_t rate, uint32_t channels,
			     uint16_t bits_per_sample, bool use_default_chmap,
			     bool use_back_flavor, u8 *channel_map,
			     uint16_t sample_word_size);

int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
			uint32_t rate, uint32_t channels,
			uint16_t bits_per_sample);

int q6asm_enc_cfg_blk_pcm_format_support_v3(struct audio_client *ac,
					    uint32_t rate, uint32_t channels,
					    uint16_t bits_per_sample,
					    uint16_t sample_word_size);

int q6asm_set_encdec_chan_map(struct audio_client *ac,
		uint32_t num_channels);

@@ -393,6 +414,15 @@ int q6asm_media_format_block_pcm_format_support_v2(struct audio_client *ac,
				uint16_t bits_per_sample, int stream_id,
				bool use_default_chmap, char *channel_map);

int q6asm_media_format_block_pcm_format_support_v3(struct audio_client *ac,
						   uint32_t rate,
						   uint32_t channels,
						   uint16_t bits_per_sample,
						   int stream_id,
						   bool use_default_chmap,
						   char *channel_map,
						   uint16_t sample_word_size);

int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
			uint32_t rate, uint32_t channels,
			bool use_default_chmap, char *channel_map);
@@ -403,6 +433,13 @@ int q6asm_media_format_block_multi_ch_pcm_v2(
			bool use_default_chmap, char *channel_map,
			uint16_t bits_per_sample);

int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
					     uint32_t rate, uint32_t channels,
					     bool use_default_chmap,
					     char *channel_map,
					     uint16_t bits_per_sample,
					     uint16_t sample_word_size);

int q6asm_media_format_block_aac(struct audio_client *ac,
			struct asm_aac_cfg *cfg);

+18 −6
Original line number Diff line number Diff line
@@ -670,9 +670,10 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
	union snd_codec_options *codec_options;

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

	pr_debug("%s: use_gapless_codec_options %d\n",
			__func__, use_gapless_codec_options);
@@ -696,15 +697,26 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
			chmap =
			    pdata->ch_map[rtd->dai_link->be_id]->channel_map;
		}
		if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE)

		switch (prtd->codec_param.codec.format) {
		case SNDRV_PCM_FORMAT_S24_LE:
			bit_width = 24;
		ret = q6asm_media_format_block_pcm_format_support_v2(
			sample_word_size = 32;
			break;
		case SNDRV_PCM_FORMAT_S16_LE:
		default:
			bit_width = 16;
			sample_word_size = 16;
			break;
		}
		ret = q6asm_media_format_block_pcm_format_support_v3(
							prtd->audio_client,
							prtd->sample_rate,
							prtd->num_channels,
							bit_width, stream_id,
							use_default_chmap,
							chmap);
							chmap,
							sample_word_size);
		if (ret < 0)
			pr_err("%s: CMD Format block failed\n", __func__);

@@ -958,7 +970,7 @@ static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)
	} else {
		pr_debug("%s: stream_id %d bits_per_sample %d\n",
				__func__, ac->stream_id, bits_per_sample);
		ret = q6asm_stream_open_write_v2(ac,
		ret = q6asm_stream_open_write_v3(ac,
				prtd->codec, bits_per_sample,
				ac->stream_id,
				prtd->gapless_state.use_dsp_gapless_mode);
@@ -1865,7 +1877,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)

		pr_debug("%s: open_write stream_id %d bits_per_sample %d",
				__func__, stream_id, bits_per_sample);
		rc = q6asm_stream_open_write_v2(prtd->audio_client,
		rc = q6asm_stream_open_write_v3(prtd->audio_client,
				prtd->codec, bits_per_sample,
				stream_id,
				prtd->gapless_state.use_dsp_gapless_mode);
+15 −8
Original line number Diff line number Diff line
@@ -87,7 +87,8 @@ static struct snd_pcm_hardware msm_pcm_hardware_playback = {
				SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
				SNDRV_PCM_FMTBIT_S24_LE),
				SNDRV_PCM_FMTBIT_S24_LE |
				SNDRV_PCM_FMTBIT_S24_3LE),
	.rates =                SNDRV_PCM_RATE_8000_192000,
	.rate_min =             8000,
	.rate_max =             192000,
@@ -110,7 +111,8 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = {
				SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
				SNDRV_PCM_FMTBIT_S24_LE),
				SNDRV_PCM_FMTBIT_S24_LE |
				SNDRV_PCM_FMTBIT_S24_3LE),
	.rates =                SNDRV_PCM_RATE_8000_48000,
	.rate_min =             8000,
	.rate_max =             48000,
@@ -253,7 +255,7 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
	struct audio_buffer *buf;
	struct shared_io_config config;
	uint16_t sample_word_size;
	uint16_t bits_per_sample = 16;
	uint16_t bits_per_sample;
	int ret;
	int dir = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? IN : OUT;

@@ -280,16 +282,21 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
		return 0;

	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S16_LE:
		bits_per_sample = 16;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		bits_per_sample = 24;
		sample_word_size = 32;
		break;
	case SNDRV_PCM_FORMAT_S24_3LE:
		bits_per_sample = 24;
		sample_word_size = 24;
		break;
	case SNDRV_PCM_FORMAT_S16_LE:
	default:
		bits_per_sample = 16;
		sample_word_size = 16;
		break;
	}

	sample_word_size = (bits_per_sample == 16) ? 16 : 32;

	config.format = FORMAT_LINEAR_PCM;
	config.bits_per_sample = bits_per_sample;
	config.rate = params_rate(params);
+39 −28
Original line number Diff line number Diff line
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -276,7 +276,8 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
	struct msm_plat_data *pdata;
	struct snd_pcm_hw_params *params;
	int ret;
	uint16_t bits_per_sample = 16;
	uint16_t bits_per_sample;
	uint16_t sample_word_size;

	pdata = (struct msm_plat_data *)
		dev_get_drvdata(soc_prtd->platform->dev);
@@ -304,11 +305,21 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
	prtd->audio_client->perf_mode = pdata->perf_mode;
	pr_debug("%s: perf: %x\n", __func__, pdata->perf_mode);

	if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S24_LE:
		bits_per_sample = 24;
		sample_word_size = 32;
		break;
	case SNDRV_PCM_FORMAT_S16_LE:
	default:
		bits_per_sample = 16;
		sample_word_size = 16;
		break;
	}

	ret = q6asm_open_write_v2(prtd->audio_client,
	ret = q6asm_open_write_v3(prtd->audio_client,
				  FORMAT_LINEAR_PCM, bits_per_sample);

	if (ret < 0) {
		pr_err("%s: q6asm_open_write_v2 failed\n", __func__);
		q6asm_audio_client_free(prtd->audio_client);
@@ -331,19 +342,11 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
		return ret;
	}

	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S16_LE:
		bits_per_sample = 16;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		bits_per_sample = 24;
		break;
	}

	ret = q6asm_media_format_block_multi_ch_pcm_v2(
	ret = q6asm_media_format_block_multi_ch_pcm_v3(
				prtd->audio_client, runtime->rate,
				runtime->channels, !prtd->set_channel_map,
			prtd->channel_map, bits_per_sample);
				prtd->channel_map, bits_per_sample,
				sample_word_size);
	if (ret < 0)
		pr_info("%s: CMD Format block failed\n", __func__);

@@ -366,7 +369,8 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
	struct msm_pcm_routing_evt event;
	int ret = 0;
	int i = 0;
	uint16_t bits_per_sample = 16;
	uint16_t bits_per_sample;
	uint16_t sample_word_size;

	pdata = (struct msm_plat_data *)
		dev_get_drvdata(soc_prtd->platform->dev);
@@ -397,7 +401,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
				__func__, params_channels(params),
				prtd->audio_client->perf_mode);

		ret = q6asm_open_read_v2(prtd->audio_client, FORMAT_LINEAR_PCM,
		ret = q6asm_open_read_v3(prtd->audio_client, FORMAT_LINEAR_PCM,
				bits_per_sample);
		if (ret < 0) {
			pr_err("%s: q6asm_open_read failed\n", __func__);
@@ -443,18 +447,25 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
		return 0;

	switch (runtime->format) {
	case SNDRV_PCM_FORMAT_S16_LE:
		bits_per_sample = 16;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		bits_per_sample = 24;
		sample_word_size = 32;
		break;
	case SNDRV_PCM_FORMAT_S16_LE:
	default:
		bits_per_sample = 16;
		sample_word_size = 16;
		break;
	}
	pr_debug("Samp_rate = %d\n", prtd->samp_rate);
	pr_debug("Channel = %d\n", prtd->channel_mode);
	ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
					prtd->samp_rate, prtd->channel_mode,
					bits_per_sample);

	pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n",
			__func__, prtd->samp_rate, prtd->channel_mode,
			bits_per_sample, sample_word_size);
	ret = q6asm_enc_cfg_blk_pcm_format_support_v3(prtd->audio_client,
						      prtd->samp_rate,
						      prtd->channel_mode,
						      bits_per_sample,
						      sample_word_size);
	if (ret < 0)
		pr_debug("%s: cmd cfg pcm was block failed", __func__);

Loading