ASoC: msm: Add support for meta data in compressed TX

There is a usecase where compressed data is sent over HDMI IN to
ADSP. The format of compressed is detected in ADSP and sent through
the meta data to compressed driver. Add support for meta data in
compressed TX for this use case.

Change-Id: Idbb18fe4a0ad828e9c2e9d7beec048b3cedf002d
Signed-off-by: Subhash Chandra Bose Naripeddy <snariped@codeaurora.org>
This commit is contained in:
Subhash Chandra Bose Naripeddy 2012-06-20 20:46:13 -07:00 committed by Stephen Boyd
parent ff07abf9f4
commit d7f5276687
5 changed files with 106 additions and 11 deletions

View file

@ -1352,6 +1352,14 @@ struct asm_stream_cmd_read{
u32 uid;
} __attribute__((packed));
#define ASM_DATA_CMD_READ_COMPRESSED 0x00010DBC
struct asm_stream_cmd_read_compressed {
struct apr_hdr hdr;
u32 buf_add;
u32 buf_size;
u32 uid;
} __packed;
#define ASM_DATA_CMD_MEDIA_FORMAT_UPDATE 0x00010BDC
#define ASM_DATA_EVENT_ENC_SR_CM_NOTIFY 0x00010BDE
struct asm_stream_media_format_update{
@ -1415,6 +1423,19 @@ struct asm_data_event_read_done{
u32 id;
} __attribute__((packed));
#define ASM_DATA_EVENT_READ_COMPRESSED_DONE 0x00010DBD
struct asm_data_event_read_compressed_done {
u32 status;
u32 buffer_add;
u32 enc_frame_size;
u32 offset;
u32 msw_ts;
u32 lsw_ts;
u32 flags;
u32 num_frames;
u32 id;
} __packed;
#define ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY 0x00010C65
struct asm_data_event_sr_cm_change_notify {
u32 sample_rate;

View file

@ -56,6 +56,15 @@
#define MAX_NUM_CODEC_DESCRIPTORS 32
#define MAX_NUM_BITRATES 32
/* compressed TX */
#define MAX_NUM_FRAMES_PER_BUFFER 1
#define COMPRESSED_META_DATA_MODE 0x10
#define META_DATA_LEN_BYTES 36
#define Q6_AC3_DECODER 0x00010BF6
#define Q6_EAC3_DECODER 0x00010C3C
#define Q6_DTS 0x00010D88
#define Q6_DTS_LBR 0x00010DBB
/* Codecs are listed linearly to allow for extensibility */
#define SND_AUDIOCODEC_PCM ((__u32) 0x00000001)
#define SND_AUDIOCODEC_MP3 ((__u32) 0x00000002)

View file

@ -183,7 +183,8 @@ int q6asm_audio_client_buf_free_contiguous(unsigned int dir,
int q6asm_open_read(struct audio_client *ac, uint32_t format);
int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format);
int q6asm_open_read_compressed(struct audio_client *ac,
uint32_t frames_per_buffer, uint32_t meta_data_mode);
int q6asm_open_write(struct audio_client *ac, uint32_t format);
@ -204,6 +205,9 @@ int q6asm_async_write(struct audio_client *ac,
int q6asm_async_read(struct audio_client *ac,
struct audio_aio_read_param *param);
int q6asm_async_read_compressed(struct audio_client *ac,
struct audio_aio_read_param *param);
int q6asm_read(struct audio_client *ac);
int q6asm_read_nolock(struct audio_client *ac);

View file

@ -38,8 +38,9 @@
/* Allocate the worst case frame size for compressed audio */
#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info))
#define COMPRE_CAPTURE_MAX_FRAME_SIZE (6144)
#define COMPRE_CAPTURE_PERIOD_SIZE (COMPRE_CAPTURE_MAX_FRAME_SIZE + \
COMPRE_CAPTURE_HEADER_SIZE)
#define COMPRE_CAPTURE_PERIOD_SIZE ((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
COMPRE_CAPTURE_HEADER_SIZE) * \
MAX_NUM_FRAMES_PER_BUFFER)
struct snd_msm {
struct msm_audio *prtd;
@ -207,6 +208,31 @@ static void compr_event_handler(uint32_t opcode,
q6asm_async_read(prtd->audio_client, &read_param);
break;
}
case ASM_DATA_EVENT_READ_COMPRESSED_DONE: {
pr_debug("ASM_DATA_EVENT_READ_COMPRESSED_DONE\n");
pr_debug("buf = %p, data = 0x%X, *data = %p,\n"
"prtd->pcm_irq_pos = %d\n",
prtd->audio_client->port[OUT].buf,
*(uint32_t *)prtd->audio_client->port[OUT].buf->data,
prtd->audio_client->port[OUT].buf->data,
prtd->pcm_irq_pos);
if (!atomic_read(&prtd->start))
break;
buf = prtd->audio_client->port[OUT].buf;
pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%X\n",
prtd->pcm_irq_pos, (uint32_t)buf[0].phys);
read_param.len = prtd->pcm_count;
read_param.paddr = (unsigned long)(buf[0].phys) +
prtd->pcm_irq_pos;
prtd->pcm_irq_pos += prtd->pcm_count;
if (atomic_read(&prtd->start))
snd_pcm_period_elapsed(substream);
q6asm_async_read_compressed(prtd->audio_client, &read_param);
break;
}
case APR_BASIC_RSP_RESULT: {
switch (payload[0]) {
case ASM_SESSION_CMD_RUN: {
@ -392,7 +418,7 @@ static int msm_compr_capture_prepare(struct snd_pcm_substream *substream)
if (prtd->enabled)
return ret;
read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE;
read_param.len = prtd->pcm_count;
pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n"
"pcm_count = %d, periods = %d\n",
__func__, prtd->samp_rate, prtd->channel_mode,
@ -400,9 +426,8 @@ static int msm_compr_capture_prepare(struct snd_pcm_substream *substream)
for (i = 0; i < runtime->periods; i++) {
read_param.uid = i;
read_param.paddr = ((unsigned long)(buf[i].phys) +
COMPRE_CAPTURE_HEADER_SIZE);
q6asm_async_read(prtd->audio_client, &read_param);
read_param.paddr = (unsigned long)(buf[i].phys);
q6asm_async_read_compressed(prtd->audio_client, &read_param);
}
prtd->periods = runtime->periods;
@ -749,7 +774,8 @@ static int msm_compr_hw_params(struct snd_pcm_substream *substream,
}
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
ret = q6asm_open_read_compressed(prtd->audio_client,
compr->codec);
MAX_NUM_FRAMES_PER_BUFFER,
COMPRESSED_META_DATA_MODE);
if (ret < 0) {
pr_err("%s: compressed Session out open failed\n",

View file

@ -1276,7 +1276,8 @@ fail_cmd:
return -EINVAL;
}
int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format)
int q6asm_open_read_compressed(struct audio_client *ac,
uint32_t frames_per_buffer, uint32_t meta_data_mode)
{
int rc = 0x00;
struct asm_stream_cmd_open_read_compressed open;
@ -1292,8 +1293,8 @@ int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format)
q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_COMPRESSED;
/* hardcoded as following*/
open.frame_per_buf = 1;
open.uMode = 0;
open.frame_per_buf = frames_per_buffer;
open.uMode = meta_data_mode;
rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
if (rc < 0) {
@ -3266,6 +3267,40 @@ fail_cmd:
return -EINVAL;
}
int q6asm_async_read_compressed(struct audio_client *ac,
struct audio_aio_read_param *param)
{
int rc = 0;
struct asm_stream_cmd_read read;
if (!ac || ac->apr == NULL) {
pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
/* Pass physical address as token for AIO scheme */
read.hdr.token = param->paddr;
read.hdr.opcode = ASM_DATA_CMD_READ_COMPRESSED;
read.buf_add = param->paddr;
read.buf_size = param->len;
read.uid = param->uid;
pr_debug("%s: session[%d] bufadd[0x%x]len[0x%x]", __func__, ac->session,
read.buf_add, read.buf_size);
rc = apr_send_pkt(ac->apr, (uint32_t *) &read);
if (rc < 0) {
pr_debug("[%s] read op[0x%x]rc[%d]\n", __func__,
read.hdr.opcode, rc);
goto fail_cmd;
}
return 0;
fail_cmd:
return -EINVAL;
}
int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
uint32_t lsw_ts, uint32_t flags)
{