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

Commit 160813b8 authored by Satish Babu Patakokila's avatar Satish Babu Patakokila
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 04947ea3
Loading
Loading
Loading
Loading
+6 −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

@@ -175,6 +180,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 {
+23 −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,24 @@ 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
 * @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
+38 −5
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

@@ -132,6 +136,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 offset */

	int32_t first_buffer;
	int32_t last_buffer;
	int32_t partial_drain_delay;
@@ -380,19 +386,23 @@ 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;
	}

	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.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);
@@ -423,6 +433,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__);
@@ -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",
				 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;
@@ -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",
			__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);
@@ -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_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,
+17 −6
Original line number 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,
			     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;
	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:
		open.mode_flags |= 0x00;
		open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
		if (ts_mode)
			open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE;
		break;
	case FORMAT_MPEG4_AAC:
		open.mode_flags |= BUFFER_META_ENABLE;
@@ -2391,14 +2394,16 @@ int q6asm_open_read(struct audio_client *ac,
		uint32_t format)
{
	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,
			uint16_t 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)
{
	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);

@@ -2427,7 +2433,8 @@ 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,
				 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);

@@ -7150,6 +7157,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;
	}