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: Satish Babu Patakokila <sbpata@codeaurora.org>
This commit is contained in:
Satish Babu Patakokila 2016-08-03 20:47:59 +05:30
parent 04947ea3d8
commit 160813b82f
4 changed files with 84 additions and 12 deletions

View file

@ -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 {

View file

@ -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

View file

@ -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,

View file

@ -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;
}