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

Commit 17153ab7 authored by Satish Babu Patakokila's avatar Satish Babu Patakokila Committed by Gerrit - the friendly Code Review server
Browse files

ASoc: msm: qdsp6v2: Add timestamp support for compress capture



Add timestamp support for compress driver.
Modify asm driver to read the buffer from predefined offset.

CRs-fixed: 1072067
Change-Id: I1c46befc223285495b3c0650e6c3eaae81f58771
Signed-off-by: default avatarSatish Babu Patakokila <sbpata@codeaurora.org>
parent bc92ad08
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -73,6 +73,11 @@
/* bit 4 represents META enable of encoded data buffer */
#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 */
#define SR_CM_NOTIFY_ENABLE	0x0004

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

struct audio_port_data {
@@ -246,6 +252,9 @@ int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
		       uint16_t bits_per_sample);

int q6asm_open_read_v4(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*/);

+14 −1
Original line number Diff line number Diff line
@@ -70,6 +70,11 @@
#define Q6_DTS		0x00010D88
#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 */
#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
@@ -480,7 +485,15 @@ struct snd_codec {
	__u32 align;
	__u32 compr_passthr;
	union snd_codec_options options;
	__u32 reserved[3];
	__u32 flags;
	__u32 reserved[2];
} __attribute__((packed, aligned(4)));

struct snd_codec_metadata {
	__u32 length;
	__u32 offset;
	__u64 timestamp;
	__u32 reserved[4];
};

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

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

/* decoder parameter length */
#define DDP_DEC_MAX_NUM_PARAM		18

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

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

	int32_t first_buffer;
	int32_t last_buffer;
	int32_t partial_drain_delay;
@@ -402,26 +408,31 @@ static int msm_compr_read_buffer(struct msm_compr_audio *prtd)
		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;
	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",
				__func__, bytes_available);
		return 0;
	}

	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.uid = buffer_length;
	param.flags = prtd->codec_param.codec.flags;

	pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
			__func__, buffer_length, prtd->bytes_read);
	if (q6asm_async_read(prtd->audio_client, &param) < 0) {
		pr_err("%s:q6asm_async_read failed\n", __func__);
	} else {
		prtd->bytes_read += buffer_length;
		prtd->bytes_read_offset += buffer_length;
		prtd->bytes_read += buffer_length + prtd->ts_header_offset;
		prtd->bytes_read_offset += buffer_length +
							prtd->ts_header_offset;
		if (prtd->bytes_read_offset >= prtd->buffer_size)
			prtd->bytes_read_offset -= prtd->buffer_size;
	}
@@ -442,6 +453,7 @@ static void compr_event_handler(uint32_t opcode,
	uint32_t stream_index;
	unsigned long flags;
	uint64_t read_size;
	uint32_t *buff_addr;

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

		pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
				 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 */
		read_size = prtd->codec_param.buffer.fragment_size;
		prtd->byte_offset += read_size;
@@ -1232,7 +1261,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",
			__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);
	if (ret < 0) {
		pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret);
@@ -1283,6 +1312,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_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",
			__func__, prtd->sample_rate, prtd->num_channels,
+26 −5
Original line number Diff line number Diff line
@@ -2201,7 +2201,7 @@ static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr,

static int __q6asm_open_read(struct audio_client *ac,
			     uint32_t format, uint16_t bits_per_sample,
			     bool use_v3_format)
			     bool use_v3_format, bool ts_mode)
{
	int rc = 0x00;
	struct asm_stream_cmd_open_read_v3 open;
@@ -2244,6 +2244,8 @@ static int __q6asm_open_read(struct audio_client *ac,
	switch (format) {
	case FORMAT_LINEAR_PCM:
		open.mode_flags |= 0x00;
		if (ts_mode)
			open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE;
		if (use_v3_format)
			open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
		else
@@ -2318,14 +2320,14 @@ int q6asm_open_read(struct audio_client *ac,
		uint32_t format)
{
	return __q6asm_open_read(ac, format, 16,
				 false /*use_v3_format*/);
				 false /*use_v3_format*/, false/*ts_mode*/);
}

int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample)
{
	return __q6asm_open_read(ac, format, bits_per_sample,
				 false /*use_v3_format*/);
				 false /*use_v3_format*/, false/*ts_mode*/);
}

/*
@@ -2339,10 +2341,25 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample)
{
	return __q6asm_open_read(ac, format, bits_per_sample,
				 true /*use_v3_format*/);
				 true /*use_v3_format*/, false/*ts_mode*/);
}
EXPORT_SYMBOL(q6asm_open_read_v3);

/*
 * asm_open_read_v4 - Opens audio capture session
 *
 * @ac: Client session handle
 * @format: encoder format
 * @bits_per_sample: bit width of capture session
 */
int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
			uint16_t bits_per_sample)
{
	return __q6asm_open_read(ac, format, bits_per_sample,
				true /*use_v3_format*/, true/*ts_mode*/);
}
EXPORT_SYMBOL(q6asm_open_read_v4);

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