diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2017-03-14 23:45:47 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-03-14 23:45:46 -0700 |
commit | 7a17dfedc6ca72b849af34439e0c4831370d5290 (patch) | |
tree | 5d7e427f9567bfbd3d5aa5ef26f8ce7d6ac1ee26 /sound/soc | |
parent | 3961be10c40b6629a2e5b4c1e0bc092f8e88712b (diff) | |
parent | 4dd51b1015ba07645882fec09159824e8c9b6a90 (diff) |
Merge "ASoc: msm: qdsp6v2: Add timestamp support for offload playback"
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 60 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/q6asm.c | 10 |
2 files changed, 52 insertions, 18 deletions
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 4fa80c679b46..8e986a74ffff 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -56,8 +56,8 @@ #define FLAC_BLK_SIZE_LIMIT 65535 /* Timestamp mode payload offsets */ -#define TS_LSW_OFFSET 6 -#define TS_MSW_OFFSET 7 +#define CAPTURE_META_DATA_TS_OFFSET_LSW 6 +#define CAPTURE_META_DATA_TS_OFFSET_MSW 7 /* decoder parameter length */ #define DDP_DEC_MAX_NUM_PARAM 18 @@ -410,6 +410,7 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd) int buffer_length; uint64_t bytes_available; struct audio_aio_write_param param; + struct snd_codec_metadata *buff_addr; if (!atomic_read(&prtd->start)) { pr_err("%s: stream is not in started state\n", __func__); @@ -442,23 +443,34 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd) } if (buffer_length) { - param.paddr = prtd->buffer_paddr + prtd->byte_offset; + param.paddr = prtd->buffer_paddr + prtd->byte_offset; WARN(prtd->byte_offset % 32 != 0, "offset %x not multiple of 32", prtd->byte_offset); } else - param.paddr = prtd->buffer_paddr; - + param.paddr = prtd->buffer_paddr; param.len = buffer_length; - param.msw_ts = 0; - param.lsw_ts = 0; - param.flags = NO_TIMESTAMP; + if (prtd->ts_header_offset) { + buff_addr = (struct snd_codec_metadata *) + (prtd->buffer + prtd->byte_offset); + param.len = buff_addr->length; + param.msw_ts = (uint32_t) + ((buff_addr->timestamp & 0xFFFFFFFF00000000LL) >> 32); + param.lsw_ts = (uint32_t) (buff_addr->timestamp & 0xFFFFFFFFLL); + param.paddr += prtd->ts_header_offset; + param.flags = SET_TIMESTAMP; + param.metadata_len = prtd->ts_header_offset; + } else { + param.msw_ts = 0; + param.lsw_ts = 0; + param.flags = NO_TIMESTAMP; + param.metadata_len = 0; + } param.uid = buffer_length; - param.metadata_len = 0; param.last_buffer = prtd->last_buffer; pr_debug("%s: sending %d bytes to DSP byte_offset = %d\n", - __func__, buffer_length, prtd->byte_offset); + __func__, param.len, prtd->byte_offset); if (q6asm_async_write(prtd->audio_client, ¶m) < 0) { pr_err("%s:q6asm_async_write failed\n", __func__); } else { @@ -577,9 +589,21 @@ static void compr_event_handler(uint32_t opcode, * written to ADSP in the last write, update offset and * total copied data accordingly. */ - - prtd->byte_offset += token; - prtd->copied_total += token; + if (prtd->ts_header_offset) { + /* Always assume that the data will be sent to DSP on + * frame boundary. + * i.e, one frame of userspace write will result in + * one kernel write to DSP. This is needed as + * timestamp will be sent per frame. + */ + prtd->byte_offset += + prtd->codec_param.buffer.fragment_size; + prtd->copied_total += + prtd->codec_param.buffer.fragment_size; + } else { + prtd->byte_offset += token; + prtd->copied_total += token; + } if (prtd->byte_offset >= prtd->buffer_size) prtd->byte_offset -= prtd->buffer_size; @@ -634,10 +658,10 @@ static void compr_event_handler(uint32_t opcode, *buff_addr = prtd->ts_header_offset; buff_addr++; /* Write the TS LSW */ - *buff_addr = payload[TS_LSW_OFFSET]; + *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_LSW]; buff_addr++; /* Write the TS MSW */ - *buff_addr = payload[TS_MSW_OFFSET]; + *buff_addr = payload[CAPTURE_META_DATA_TS_OFFSET_MSW]; } /* Always assume read_size is same as fragment_size */ read_size = prtd->codec_param.buffer.fragment_size; @@ -1320,6 +1344,12 @@ static int msm_compr_configure_dsp_for_playback 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; + ret = msm_compr_send_media_format_block(cstream, ac->stream_id, false); if (ret < 0) { pr_err("%s, failed to send media format block\n", __func__); diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index c3a4719542ef..f38108258306 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -7466,9 +7466,13 @@ int q6asm_async_write(struct audio_client *ac, else if (ac->io_mode == io_compressed || ac->io_mode == io_compressed_stream) lbuf_phys_addr = (param->paddr - param->metadata_len); - else - lbuf_phys_addr = param->paddr; - + else { + if (param->flags & SET_TIMESTAMP) + lbuf_phys_addr = param->paddr - + sizeof(struct snd_codec_metadata); + else + lbuf_phys_addr = param->paddr; + } dev_vdbg(ac->dev, "%s: token[0x%x], buf_addr[%pK], buf_size[0x%x], ts_msw[0x%x], ts_lsw[0x%x], lbuf_phys_addr: 0x[%pK]\n", __func__, write.hdr.token, ¶m->paddr, |