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

Commit 74e95335 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: Add TX app type support in compress driver"

parents 15b248e3 0661cfb2
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -73,6 +73,11 @@
/* bit 4 represents META enable of encoded data buffer */
/* bit 4 represents META enable of encoded data buffer */
#define BUFFER_META_ENABLE	0x0010
#define BUFFER_META_ENABLE	0x0010


/* bit 5 represents timestamp */
/* bit 5 - 0 -- ASM_DATA_EVENT_READ_DONE will have relative time-stamp*/
/* bit 5 - 1 -- ASM_DATA_EVENT_READ_DONE will have absolute time-stamp*/
#define ABSOLUTE_TIMESTAMP_ENABLE  0x0020

/* Enable Sample_Rate/Channel_Mode notification event from Decoder */
/* Enable Sample_Rate/Channel_Mode notification event from Decoder */
#define SR_CM_NOTIFY_ENABLE	0x0004
#define SR_CM_NOTIFY_ENABLE	0x0004


@@ -175,6 +180,7 @@ struct audio_aio_read_param {
	phys_addr_t   paddr;
	phys_addr_t   paddr;
	uint32_t      len;
	uint32_t      len;
	uint32_t      uid;
	uint32_t      uid;
	uint32_t      flags;/*meta data flags*/
};
};


struct audio_port_data {
struct audio_port_data {
+23 −1
Original line number Original line Diff line number Diff line
@@ -70,6 +70,11 @@
#define Q6_DTS		0x00010D88
#define Q6_DTS		0x00010D88
#define Q6_DTS_LBR	0x00010DBB
#define Q6_DTS_LBR	0x00010DBB


/* Timestamp flsg */
/* Bit-0 - 1 : Enable Timestamp mode */
/* Bit-0 - 0 : Disable Timestamp mode */
#define COMPRESSED_TIMESTAMP_FLAG 0x0001

/* Codecs are listed linearly to allow for extensibility */
/* Codecs are listed linearly to allow for extensibility */
#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
@@ -480,7 +485,24 @@ struct snd_codec {
	__u32 align;
	__u32 align;
	__u32 compr_passthr;
	__u32 compr_passthr;
	union snd_codec_options options;
	union snd_codec_options options;
	__u32 reserved[3];
	__u32 flags;
	__u32 reserved[2];
} __attribute__((packed, aligned(4)));
} __attribute__((packed, aligned(4)));



/** struct snd_codec_metadata
 * @length: Length of the encoded buffer.
 * @offset: Offset from the buffer address to the first byte of the first
 *		encoded frame. All encoded frames are consecutive starting
 *		from this offset.
 * @timestamp: Session time in microseconds of the first sample in the buffer.
 * @reserved: Reserved for future use.
 */
struct snd_codec_metadata {
	__u32 length;
	__u32 offset;
	__u64 timestamp;
	__u32 reserved[4];
};

#endif
#endif
+135 −18
Original line number Original line Diff line number Diff line
@@ -55,6 +55,10 @@
#define DSP_NUM_OUTPUT_FRAME_BUFFERED	2
#define DSP_NUM_OUTPUT_FRAME_BUFFERED	2
#define FLAC_BLK_SIZE_LIMIT		65535
#define FLAC_BLK_SIZE_LIMIT		65535


/* Timestamp mode payload offsets */
#define TS_LSW_OFFSET			6
#define TS_MSW_OFFSET			7

/* decoder parameter length */
/* decoder parameter length */
#define DDP_DEC_MAX_NUM_PARAM		18
#define DDP_DEC_MAX_NUM_PARAM		18


@@ -132,6 +136,8 @@ struct msm_compr_audio {
	uint64_t bytes_read; /* from DSP */
	uint64_t bytes_read; /* from DSP */
	uint32_t bytes_read_offset; /* bytes read offset */
	uint32_t bytes_read_offset; /* bytes read offset */


	uint32_t ts_header_offset; /* holds the timestamp header offset */

	int32_t first_buffer;
	int32_t first_buffer;
	int32_t last_buffer;
	int32_t last_buffer;
	int32_t partial_drain_delay;
	int32_t partial_drain_delay;
@@ -380,19 +386,23 @@ static int msm_compr_read_buffer(struct msm_compr_audio *prtd)
		return -EINVAL;
		return -EINVAL;
	}
	}


	buffer_length = prtd->codec_param.buffer.fragment_size;
	buffer_length = prtd->codec_param.buffer.fragment_size -
						 prtd->ts_header_offset;
	bytes_available = prtd->received_total - prtd->bytes_copied;
	bytes_available = prtd->received_total - prtd->bytes_copied;
	buffer_sent = prtd->bytes_read - prtd->bytes_copied;
	buffer_sent = prtd->bytes_read - prtd->bytes_copied;
	if (buffer_sent + buffer_length > prtd->buffer_size) {
	if (buffer_sent + buffer_length + prtd->ts_header_offset
						> prtd->buffer_size) {
		pr_debug(" %s : Buffer is Full bytes_available: %llu\n",
		pr_debug(" %s : Buffer is Full bytes_available: %llu\n",
				__func__, bytes_available);
				__func__, bytes_available);
		return 0;
		return 0;
	}
	}


	memset(&param, 0x0, sizeof(struct audio_aio_read_param));
	memset(&param, 0x0, sizeof(struct audio_aio_read_param));
	param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset;
	param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset +
						prtd->ts_header_offset;
	param.len = buffer_length;
	param.len = buffer_length;
	param.uid = buffer_length;
	param.uid = buffer_length;
	param.flags = prtd->codec_param.codec.flags;


	pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
	pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
			__func__, buffer_length, prtd->bytes_read);
			__func__, buffer_length, prtd->bytes_read);
@@ -423,6 +433,7 @@ static void compr_event_handler(uint32_t opcode,
	uint32_t stream_index;
	uint32_t stream_index;
	unsigned long flags;
	unsigned long flags;
	uint64_t read_size;
	uint64_t read_size;
	uint32_t *buff_addr;


	if (!prtd) {
	if (!prtd) {
		pr_err("%s: prtd is NULL\n", __func__);
		pr_err("%s: prtd is NULL\n", __func__);
@@ -514,6 +525,23 @@ static void compr_event_handler(uint32_t opcode,


		pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
		pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
				 prtd->byte_offset, payload[4]);
				 prtd->byte_offset, payload[4]);

		if (prtd->ts_header_offset) {
			/* Update the header for received buffer */
			buff_addr = prtd->buffer + prtd->byte_offset;
			/* Write the length of the buffer */
			*buff_addr = prtd->codec_param.buffer.fragment_size
						 - prtd->ts_header_offset;
			buff_addr++;
			/* Write the offset */
			*buff_addr = prtd->ts_header_offset;
			buff_addr++;
			/* Write the TS LSW */
			*buff_addr = payload[TS_LSW_OFFSET];
			buff_addr++;
			/* Write the TS MSW */
			*buff_addr = payload[TS_MSW_OFFSET];
		}
		/* Always assume read_size is same as fragment_size */
		/* Always assume read_size is same as fragment_size */
		read_size = prtd->codec_param.buffer.fragment_size;
		read_size = prtd->codec_param.buffer.fragment_size;
		prtd->byte_offset += read_size;
		prtd->byte_offset += read_size;
@@ -1214,7 +1242,7 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
	pr_debug("%s: stream_id %d bits_per_sample %d\n",
	pr_debug("%s: stream_id %d bits_per_sample %d\n",
			__func__, ac->stream_id, bits_per_sample);
			__func__, ac->stream_id, bits_per_sample);


	ret = q6asm_open_read_v3(prtd->audio_client, FORMAT_LINEAR_PCM,
	ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
		bits_per_sample);
		bits_per_sample);
	if (ret < 0) {
	if (ret < 0) {
		pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret);
		pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret);
@@ -1265,6 +1293,11 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
	prtd->buffer_paddr   = ac->port[dir].buf[0].phys;
	prtd->buffer_paddr   = ac->port[dir].buf[0].phys;
	prtd->buffer_size    = runtime->fragments * runtime->fragment_size;
	prtd->buffer_size    = runtime->fragments * runtime->fragment_size;


	/* Bit-0 of flags represent timestamp mode */
	if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
		prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
	else
		prtd->ts_header_offset = 0;


	pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
	pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
			__func__, prtd->sample_rate, prtd->num_channels,
			__func__, prtd->sample_rate, prtd->num_channels,
@@ -3146,7 +3179,7 @@ static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
	return 0;
	return 0;
}
}


static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol,
static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
				      struct snd_ctl_elem_value *ucontrol)
{
{
	u64 fe_id = kcontrol->private_value;
	u64 fe_id = kcontrol->private_value;
@@ -3173,7 +3206,7 @@ static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol,
	return 0;
	return 0;
}
}


static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol,
static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
				      struct snd_ctl_elem_value *ucontrol)
{
{
	u64 fe_id = kcontrol->private_value;
	u64 fe_id = kcontrol->private_value;
@@ -3208,6 +3241,68 @@ done:
	return ret;
	return ret;
}
}


static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	u64 fe_id = kcontrol->private_value;
	int app_type;
	int acdb_dev_id;
	int sample_rate = 48000;

	pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
		pr_err("%s Received out of bounds fe_id %llu\n",
			__func__, fe_id);
		return -EINVAL;
	}

	app_type = ucontrol->value.integer.value[0];
	acdb_dev_id = ucontrol->value.integer.value[1];
	if (ucontrol->value.integer.value[2] != 0)
		sample_rate = ucontrol->value.integer.value[2];
	pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n",
		__func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX);
	msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type,
		acdb_dev_id, sample_rate, SESSION_TYPE_TX);

	return 0;
}

static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	u64 fe_id = kcontrol->private_value;
	int ret = 0;
	int app_type;
	int acdb_dev_id;
	int sample_rate;

	pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
		pr_err("%s Received out of bounds fe_id %llu\n",
			__func__, fe_id);
		ret = -EINVAL;
		goto done;
	}

	ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX,
		&app_type, &acdb_dev_id, &sample_rate);
	if (ret < 0) {
		pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
			__func__, ret);
		goto done;
	}

	ucontrol->value.integer.value[0] = app_type;
	ucontrol->value.integer.value[1] = acdb_dev_id;
	ucontrol->value.integer.value[2] = sample_rate;
	pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
		__func__, fe_id, SESSION_TYPE_TX,
		app_type, acdb_dev_id, sample_rate);
done:
	return ret;
}

static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
				     struct snd_ctl_elem_value *ucontrol)
{
{
@@ -3595,7 +3690,8 @@ static int msm_compr_add_dec_runtime_params_control(


static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
{
{
	const char *mixer_ctl_name	= "Audio Stream";
	const char *playback_mixer_ctl_name	= "Audio Stream";
	const char *capture_mixer_ctl_name	= "Audio Stream Capture";
	const char *deviceNo		= "NN";
	const char *deviceNo		= "NN";
	const char *suffix		= "App Type Cfg";
	const char *suffix		= "App Type Cfg";
	char *mixer_str = NULL;
	char *mixer_str = NULL;
@@ -3606,8 +3702,8 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
		.name = "?",
		.name = "?",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_compr_app_type_cfg_info,
		.info = msm_compr_app_type_cfg_info,
		.put = msm_compr_app_type_cfg_put,
		.put = msm_compr_playback_app_type_cfg_put,
		.get = msm_compr_app_type_cfg_get,
		.get = msm_compr_playback_app_type_cfg_get,
		.private_value = 0,
		.private_value = 0,
		}
		}
	};
	};
@@ -3620,9 +3716,13 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
	pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
	pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
		__func__, rtd->dai_link->name, rtd->dai_link->be_id,
		__func__, rtd->dai_link->name, rtd->dai_link->be_id,
			rtd->dai_link->cpu_dai_name, rtd->pcm->device);
			rtd->dai_link->cpu_dai_name, rtd->pcm->device);
	if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
		ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo)
			 + 1 + strlen(suffix) + 1;
	else
		ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo)
			+ 1 + strlen(suffix) + 1;


	ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
		  strlen(suffix) + 1;
	mixer_str = kzalloc(ctl_len, GFP_KERNEL);
	mixer_str = kzalloc(ctl_len, GFP_KERNEL);


	if (!mixer_str) {
	if (!mixer_str) {
@@ -3630,10 +3730,27 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
		return 0;
		return 0;
	}
	}


	snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
	if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
		 rtd->pcm->device, suffix);
		snprintf(mixer_str, ctl_len, "%s %d %s",
			 playback_mixer_ctl_name, rtd->pcm->device, suffix);
	else
		snprintf(mixer_str, ctl_len, "%s %d %s",
			 capture_mixer_ctl_name, rtd->pcm->device, suffix);

	fe_app_type_cfg_control[0].name = mixer_str;
	fe_app_type_cfg_control[0].name = mixer_str;
	fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id;
	fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id;

	if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
		fe_app_type_cfg_control[0].put =
					 msm_compr_playback_app_type_cfg_put;
		fe_app_type_cfg_control[0].get =
					 msm_compr_playback_app_type_cfg_get;
	} else {
		fe_app_type_cfg_control[0].put =
					 msm_compr_capture_app_type_cfg_put;
		fe_app_type_cfg_control[0].get =
					 msm_compr_capture_app_type_cfg_get;
	}
	pr_debug("Registering new mixer ctl %s", mixer_str);
	pr_debug("Registering new mixer ctl %s", mixer_str);
	snd_soc_add_platform_controls(rtd->platform,
	snd_soc_add_platform_controls(rtd->platform,
				fe_app_type_cfg_control,
				fe_app_type_cfg_control,
+17 −6
Original line number Original line Diff line number Diff line
@@ -2285,7 +2285,8 @@ static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr,


static int __q6asm_open_read(struct audio_client *ac,
static int __q6asm_open_read(struct audio_client *ac,
			     uint32_t format, uint16_t bits_per_sample,
			     uint32_t format, uint16_t bits_per_sample,
			     uint32_t pcm_format_block_ver)
			     uint32_t pcm_format_block_ver,
			     bool ts_mode)
{
{
	int rc = 0x00;
	int rc = 0x00;
	struct asm_stream_cmd_open_read_v3 open;
	struct asm_stream_cmd_open_read_v3 open;
@@ -2329,6 +2330,8 @@ static int __q6asm_open_read(struct audio_client *ac,
	case FORMAT_LINEAR_PCM:
	case FORMAT_LINEAR_PCM:
		open.mode_flags |= 0x00;
		open.mode_flags |= 0x00;
		open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
		open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
		if (ts_mode)
			open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE;
		break;
		break;
	case FORMAT_MPEG4_AAC:
	case FORMAT_MPEG4_AAC:
		open.mode_flags |= BUFFER_META_ENABLE;
		open.mode_flags |= BUFFER_META_ENABLE;
@@ -2391,14 +2394,16 @@ int q6asm_open_read(struct audio_client *ac,
		uint32_t format)
		uint32_t format)
{
{
	return __q6asm_open_read(ac, format, 16,
	return __q6asm_open_read(ac, format, 16,
				PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/);
				PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
				false/*ts_mode*/);
}
}


int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample)
			uint16_t bits_per_sample)
{
{
	return __q6asm_open_read(ac, format, bits_per_sample,
	return __q6asm_open_read(ac, format, bits_per_sample,
				 PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/);
				 PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
				 false/*ts_mode*/);
}
}


/*
/*
@@ -2412,7 +2417,8 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample)
			uint16_t bits_per_sample)
{
{
	return __q6asm_open_read(ac, format, bits_per_sample,
	return __q6asm_open_read(ac, format, bits_per_sample,
				 PCM_MEDIA_FORMAT_V3/*media fmt block ver*/);
				 PCM_MEDIA_FORMAT_V3/*media fmt block ver*/,
				 false/*ts_mode*/);
}
}
EXPORT_SYMBOL(q6asm_open_read_v3);
EXPORT_SYMBOL(q6asm_open_read_v3);


@@ -2427,7 +2433,8 @@ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample)
			uint16_t bits_per_sample)
{
{
	return __q6asm_open_read(ac, format, bits_per_sample,
	return __q6asm_open_read(ac, format, bits_per_sample,
				 PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/);
				 PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/,
				 true/*ts_mode*/);
}
}
EXPORT_SYMBOL(q6asm_open_read_v4);
EXPORT_SYMBOL(q6asm_open_read_v4);


@@ -7150,6 +7157,10 @@ int q6asm_async_read(struct audio_client *ac,
		lbuf_phys_addr = (param->paddr - 64);
		lbuf_phys_addr = (param->paddr - 64);
		dir = OUT;
		dir = OUT;
	} else {
	} else {
		if (param->flags & COMPRESSED_TIMESTAMP_FLAG)
			lbuf_phys_addr = param->paddr -
				 sizeof(struct snd_codec_metadata);
		else
			lbuf_phys_addr = param->paddr;
			lbuf_phys_addr = param->paddr;
		dir = OUT;
		dir = OUT;
	}
	}