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:
parent
04947ea3d8
commit
160813b82f
4 changed files with 84 additions and 12 deletions
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue