diff options
| -rw-r--r-- | include/sound/q6asm-v2.h | 6 | ||||
| -rw-r--r-- | include/uapi/sound/compress_params.h | 24 | ||||
| -rw-r--r-- | sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 43 | ||||
| -rw-r--r-- | sound/soc/msm/qdsp6v2/q6asm.c | 23 |
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(¶m, 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; } |
