ASoC: msm: qdsp6: Add APIs for compressed audio playback/capture
Add APIs for compressed audio playback/capture in pass through mode
Change-Id: Ic9b4c71b518e653dae4726112edb75025ccc2bc2
Signed-off-by: Santosh Mardi <gsantosh@codeaurora.org>
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 5408a52..f71d743 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1033,6 +1033,10 @@
#define WMA_V9 0x00010BF4
#define AMR_WB_PLUS 0x00010BF5
#define AC3_DECODER 0x00010BF6
+#define EAC3_DECODER 0x00010C3C
+#define DTS 0x00010D88
+#define ATRAC 0x00010D89
+#define MAT 0x00010D8A
#define G711_ALAW_FS 0x00010BF7
#define G711_MLAW_FS 0x00010BF8
#define G711_PCM_FS 0x00010BF9
@@ -1059,6 +1063,16 @@
u32 format;
} __attribute__((packed));
+#define IEC_61937_MASK 0x00000001
+#define IEC_60958_MASK 0x00000002
+
+#define ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED 0x00010D84
+struct asm_stream_cmd_open_write_compressed {
+ struct apr_hdr hdr;
+ u32 flags;
+ u32 format;
+} __packed;
+
#define ASM_STREAM_CMD_OPEN_READWRITE 0x00010BCC
struct asm_stream_cmd_open_read_write {
@@ -1069,6 +1083,15 @@
u32 read_format;
} __attribute__((packed));
+#define ADM_CMD_CONNECT_AFE_PORT 0x00010320
+
+struct adm_cmd_connect_afe_port {
+ struct apr_hdr hdr;
+ u8 mode; /*mode represent the interface is for RX or TX*/
+ u8 session_id; /*ASM session ID*/
+ u16 afe_port_id;
+} __packed;
+
#define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10
#define ASM_STREAM_CMD_GET_ENCDEC_PARAM 0x00010C11
#define ASM_ENCDEC_CFG_BLK_ID 0x00010C2C
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index fe25d22..29fb606 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -40,6 +40,8 @@
int adm_matrix_map(int session_id, int path, int num_copps,
unsigned int *port_id, int copp_id);
+int adm_connect_afe_port(int mode, int session_id, int port_id);
+
#ifdef CONFIG_RTAC
int adm_get_copp_id(int port_id);
#endif
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 0fabc5b..c3d4bd5 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -43,6 +43,12 @@
#define FORMAT_AMR_WB_PLUS 0x0010
#define FORMAT_MPEG4_MULTI_AAC 0x0011
#define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
+#define FORMAT_AC3 0x0013
+#define FORMAT_DTS 0x0014
+#define FORMAT_EAC3 0x0015
+#define FORMAT_ATRAC 0x0016
+#define FORMAT_MAT 0x0017
+#define FORMAT_AAC 0x0018
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -175,6 +181,8 @@
int q6asm_open_write(struct audio_client *ac, uint32_t format);
+int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format);
+
int q6asm_open_read_write(struct audio_client *ac,
uint32_t rd_format,
uint32_t wr_format);
diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
index 5080e13..232c2a2 100644
--- a/include/sound/snd_compress_params.h
+++ b/include/sound/snd_compress_params.h
@@ -69,7 +69,8 @@
#define SND_AUDIOCODEC_IEC61937 ((__u32) 0x0000000B)
#define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C)
#define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D)
-
+#define SND_AUDIOCODEC_AC3 ((__u32) 0x0000000E)
+#define SND_AUDIOCODEC_DTS ((__u32) 0x0000000F)
/*
* Profile and modes are listed with bit masks. This allows for a
* more compact representation of fields that will not evolve
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index f928c00..405c7b0 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -82,7 +82,7 @@
return 0;
}
if (data->opcode == APR_BASIC_RSP_RESULT) {
- pr_debug("APR_BASIC_RSP_RESULT\n");
+ pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
switch (payload[0]) {
case ADM_CMD_SET_PARAMS:
if (rtac_make_adm_callback(payload,
@@ -94,7 +94,7 @@
case ADM_CMD_MEMORY_MAP_REGIONS:
case ADM_CMD_MEMORY_UNMAP_REGIONS:
case ADM_CMD_MATRIX_MAP_ROUTINGS:
- pr_debug("ADM_CMD_MATRIX_MAP_ROUTINGS\n");
+ case ADM_CMD_CONNECT_AFE_PORT:
atomic_set(&this_adm.copp_stat[index], 1);
wake_up(&this_adm.wait);
break;
@@ -270,6 +270,76 @@
__func__, port_id, acdb_path);
}
+int adm_connect_afe_port(int mode, int session_id, int port_id)
+{
+ struct adm_cmd_connect_afe_port cmd;
+ int ret = 0;
+ int index;
+
+ pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
+ port_id, session_id, mode);
+
+ port_id = afe_convert_virtual_to_portid(port_id);
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+ return -ENODEV;
+ }
+ if (this_adm.apr == NULL) {
+ this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+ 0xFFFFFFFF, &this_adm);
+ if (this_adm.apr == NULL) {
+ pr_err("%s: Unable to register ADM\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ rtac_set_adm_handle(this_adm.apr);
+ }
+ index = afe_get_port_index(port_id);
+ pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+ cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ cmd.hdr.pkt_size = sizeof(cmd);
+ cmd.hdr.src_svc = APR_SVC_ADM;
+ cmd.hdr.src_domain = APR_DOMAIN_APPS;
+ cmd.hdr.src_port = port_id;
+ cmd.hdr.dest_svc = APR_SVC_ADM;
+ cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+ cmd.hdr.dest_port = port_id;
+ cmd.hdr.token = port_id;
+ cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT;
+
+ cmd.mode = mode;
+ cmd.session_id = session_id;
+ cmd.afe_port_id = port_id;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
+ if (ret < 0) {
+ pr_err("%s:ADM enable for port %d failed\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ /* Wait for the callback with copp id */
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s ADM connect AFE failed for port %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ atomic_inc(&this_adm.copp_cnt[index]);
+ return 0;
+
+fail_cmd:
+
+ return ret;
+}
+
int adm_open(int port_id, int path, int rate, int channel_mode, int topology)
{
struct adm_copp_open_command open;
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index fe31b27..c7ebd2c 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -865,6 +865,7 @@
case ASM_STREAM_CMD_OPEN_READWRITE:
case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+ case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
if (atomic_read(&ac->cmd_state)) {
atomic_set(&ac->cmd_state, 0);
wake_up(&ac->cmd_wait);
@@ -1269,6 +1270,72 @@
return -EINVAL;
}
+int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format)
+{
+ int rc = 0x00;
+ struct asm_stream_cmd_open_write_compressed open;
+
+ if ((ac == NULL) || (ac->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
+ format);
+
+ q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
+
+ open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED;
+
+ switch (format) {
+ case FORMAT_AC3:
+ open.format = AC3_DECODER;
+ break;
+ case FORMAT_EAC3:
+ open.format = EAC3_DECODER;
+ break;
+ case FORMAT_MP3:
+ open.format = MP3;
+ break;
+ case FORMAT_DTS:
+ open.format = DTS;
+ break;
+ case FORMAT_AAC:
+ open.format = MPEG4_AAC;
+ break;
+ case FORMAT_ATRAC:
+ open.format = ATRAC;
+ break;
+ case FORMAT_WMA_V10PRO:
+ open.format = WMA_V10PRO;
+ break;
+ case FORMAT_MAT:
+ open.format = MAT;
+ break;
+ default:
+ pr_err("%s: Invalid format[%d]\n", __func__, format);
+ goto fail_cmd;
+ }
+ /*Below flag indicates the DSP that Compressed audio input
+ stream is not IEC 61937 or IEC 60958 packetizied*/
+ open.flags = 0x00000000;
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
+ if (rc < 0) {
+ pr_err("%s: open failed op[0x%x]rc[%d]\n", \
+ __func__, open.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
+ rc);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
int q6asm_open_write(struct audio_client *ac, uint32_t format)
{
int rc = 0x00;