summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/q6asm-v2.h6
-rw-r--r--include/uapi/sound/compress_params.h24
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c43
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c23
4 files changed, 84 insertions, 12 deletions
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index f08bd73edb59..746078936d5c 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -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 {
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
index 47367c663011..ef96966b2bbe 100644
--- a/include/uapi/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
@@ -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
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 90371b8e27f4..3851d0a370a6 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -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
@@ -130,7 +134,9 @@ struct msm_compr_audio {
uint64_t received_total; /* bytes received from DSP */
uint64_t bytes_copied; /* to userspace */
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 last_buffer;
@@ -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,
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index e3545405f61d..1a6eb5e47afe 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -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,7 +7157,11 @@ int q6asm_async_read(struct audio_client *ac,
lbuf_phys_addr = (param->paddr - 64);
dir = OUT;
} else {
- lbuf_phys_addr = param->paddr;
+ if (param->flags & COMPRESSED_TIMESTAMP_FLAG)
+ lbuf_phys_addr = param->paddr -
+ sizeof(struct snd_codec_metadata);
+ else
+ lbuf_phys_addr = param->paddr;
dir = OUT;
}