Loading include/sound/apr_audio-v2.h +19 −0 Original line number Diff line number Diff line Loading @@ -4729,6 +4729,25 @@ struct asm_stream_cmd_open_write_compressed { } __packed; /* Indicates the number of samples per channel to be removed from the beginning of the stream. */ #define ASM_DATA_CMD_REMOVE_INITIAL_SILENCE 0x00010D67 /* Indicates the number of samples per channel to be removed from the end of the stream. */ #define ASM_DATA_CMD_REMOVE_TRAILING_SILENCE 0x00010D68 struct asm_data_cmd_remove_silence { struct apr_hdr hdr; u32 num_samples_to_remove; /**< Number of samples per channel to be removed. @values 0 to (2@sscr{32}-1) */ } __packed; #define ASM_STREAM_CMD_OPEN_READ_COMPRESSED 0x00010D95 struct asm_stream_cmd_open_read_compressed { Loading include/sound/q6asm-v2.h +27 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,9 @@ #define SESSION_MAX 0x08 #define ASM_CONTROL_SESSION 0x0F #define ASM_SHIFT_GAPLESS_MODE_FLAG 31 #define ASM_SHIFT_LAST_BUFFER_FLAG 30 /* payload structure bytes */ #define READDONE_IDX_STATUS 0 #define READDONE_IDX_BUFADD_LSW 1 Loading Loading @@ -131,6 +134,7 @@ struct audio_aio_write_param { uint32_t msw_ts; uint32_t flags; uint32_t metadata_len; uint32_t last_buffer; }; struct audio_aio_read_param { Loading Loading @@ -163,12 +167,14 @@ struct audio_client { uint64_t time_stamp; struct apr_svc *apr; struct apr_svc *mmap_apr; struct apr_svc *apr2; struct mutex cmd_lock; /* idx:1 out port, 0: in port*/ struct audio_port_data port[2]; wait_queue_head_t cmd_wait; wait_queue_head_t time_wait; bool perf_mode; int stream_id; /* audio cache operations fptr*/ int (*fptr_cache_ops)(struct audio_buffer *abuff, int cache_op); }; Loading Loading @@ -204,6 +210,10 @@ int q6asm_open_write(struct audio_client *ac, uint32_t format int q6asm_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample); int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode); int q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format, uint32_t wr_format); Loading Loading @@ -240,12 +250,22 @@ int q6asm_run(struct audio_client *ac, uint32_t flags, int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts); int q6asm_stream_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id); int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable); int q6asm_reg_rx_underflow(struct audio_client *ac, uint16_t enable); int q6asm_cmd(struct audio_client *ac, int cmd); int q6asm_stream_cmd(struct audio_client *ac, int cmd, uint32_t stream_id); int q6asm_cmd_nowait(struct audio_client *ac, int cmd); int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd, uint32_t stream_id); void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size, uint32_t *idx); Loading Loading @@ -317,6 +337,9 @@ int q6asm_media_format_block_multi_ch_pcm_v2( int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg); int q6asm_stream_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id); int q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg); Loading Loading @@ -364,4 +387,8 @@ int q6asm_get_apr_service_id(int session_id); */ int q6asm_media_format_block(struct audio_client *ac, uint32_t format); /* Send the meta data to remove initial and trailing silence */ int q6asm_send_meta_data(struct audio_client *ac, uint32_t initial_samples, uint32_t trailing_samples); #endif /* __Q6_ASM_H__ */ sound/soc/msm/qdsp6v2/q6asm.c +204 −35 Original line number Diff line number Diff line Loading @@ -811,6 +811,10 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv) (apr_fn)q6asm_callback,\ ((ac->session) << 8 | 0x0001),\ ac); ac->apr2 = apr_register("ADSP", "ASM", (apr_fn)q6asm_callback, ((ac->session) << 8 | 0x0002), ac); if (ac->apr == NULL) { pr_err("%s Registration with APR failed\n", __func__); Loading Loading @@ -1210,7 +1214,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) data->token, data->payload_size, data->src_port, data->dest_port); if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) && (data->opcode != ASM_DATA_EVENT_EOS)) (data->opcode != ASM_DATA_EVENT_EOS) && (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) pr_debug("%s:Payload = [0x%x] status[0x%x]\n", __func__, payload[0], payload[1]); if (data->opcode == APR_BASIC_RSP_RESULT) { Loading Loading @@ -1244,6 +1249,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: case ASM_CMD_ADD_TOPOLOGIES: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS: pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", __func__, payload[0], payload[1]); if (atomic_read(&ac->cmd_state) && wakeup_flag) { Loading Loading @@ -1367,7 +1375,10 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) __func__, data->opcode); break; case ASM_SESSION_EVENTX_OVERFLOW: pr_err("ASM_SESSION_EVENTX_OVERFLOW\n"); pr_debug("ASM_SESSION_EVENTX_OVERFLOW\n"); break; case ASM_SESSION_EVENT_RX_UNDERFLOW: pr_debug("ASM_SESSION_EVENT_RX_UNDERFLOW\n"); break; case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3: pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n", Loading Loading @@ -1519,11 +1530,11 @@ int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac) return ret; } static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg) static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id) { pr_debug("%s:pkt_size=%d cmd_flg=%d session=%d\n", __func__, pkt_size, cmd_flg, ac->session); pr_debug("%s:pkt_size=%d cmd_flg=%d session=%d stream_id=%d\n", __func__, pkt_size, cmd_flg, ac->session, stream_id); if (ac->apr == NULL) { pr_err("%s: ac->apr is NULL", __func__); return; Loading @@ -1537,8 +1548,8 @@ static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, hdr->src_domain = APR_DOMAIN_APPS; hdr->dest_svc = APR_SVC_ASM; hdr->dest_domain = APR_DOMAIN_ADSP; hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); if (cmd_flg) { hdr->token = ac->session; atomic_set(&ac->cmd_state, 1); Loading @@ -1548,11 +1559,25 @@ static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, return; } static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg) { pr_debug("pkt_size = %d, cmd_flg = %d, session = %d\n", pkt_size, cmd_flg, ac->session); __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, ac->stream_id); return; } static void q6asm_stream_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, int32_t stream_id) { __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, stream_id); return; } static void __q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id) { pr_debug("%s pkt_size = %d, cmd_flg = %d, session = %d stream_id=%d\n", __func__, pkt_size, cmd_flg, ac->session, stream_id); hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \ APR_HDR_LEN(sizeof(struct apr_hdr)),\ APR_PKT_VER); Loading @@ -1564,8 +1589,8 @@ static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, hdr->src_domain = APR_DOMAIN_APPS; hdr->dest_svc = APR_SVC_ASM; hdr->dest_domain = APR_DOMAIN_ADSP; hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); if (cmd_flg) { hdr->token = ac->session; atomic_set(&ac->cmd_state, 1); Loading @@ -1574,6 +1599,21 @@ static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, return; } static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg) { __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg, ac->stream_id); return; } static void q6asm_stream_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, int32_t stream_id) { __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg, stream_id); return; } static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr, u32 pkt_size, u32 cmd_flg, u32 token) { Loading Loading @@ -1682,7 +1722,8 @@ int q6asm_open_read_v2(struct audio_client *ac, uint32_t format, } static int __q6asm_open_write(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample, uint32_t stream_id, bool is_gapless_mode) { int rc = 0x00; struct asm_stream_cmd_open_write_v3 open; Loading @@ -1694,14 +1735,17 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session, format); q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE); q6asm_stream_add_hdr(ac, &open.hdr, sizeof(open), TRUE, stream_id); open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3; open.mode_flags = 0x00; if (ac->perf_mode) open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION; else else { open.mode_flags |= ASM_LEGACY_STREAM_SESSION; if (is_gapless_mode) open.mode_flags |= 1 << ASM_SHIFT_GAPLESS_MODE_FLAG; } /* source endpoint : matrix */ open.sink_endpointype = ASM_END_POINT_DEVICE_MATRIX; Loading Loading @@ -1760,13 +1804,23 @@ fail_cmd: int q6asm_open_write(struct audio_client *ac, uint32_t format) { return __q6asm_open_write(ac, format, 16); return __q6asm_open_write(ac, format, 16, ac->stream_id, false /*gapless*/); } int q6asm_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) { return __q6asm_open_write(ac, format, bits_per_sample); return __q6asm_open_write(ac, format, bits_per_sample, ac->stream_id, false /*gapless*/); } int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode) { return __q6asm_open_write(ac, format, bits_per_sample, stream_id, is_gapless_mode); } int q6asm_open_read_write(struct audio_client *ac, Loading Loading @@ -1920,8 +1974,8 @@ fail_cmd: return -EINVAL; } int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts) static int __q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id) { struct asm_session_cmd_run_v2 run; int rc; Loading @@ -1930,7 +1984,7 @@ int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, return -EINVAL; } pr_debug("session[%d]", ac->session); q6asm_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE); q6asm_stream_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE, stream_id); run.hdr.opcode = ASM_SESSION_CMD_RUN_V2; run.flags = flags; Loading @@ -1948,6 +2002,17 @@ int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, return 0; } int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts) { return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, ac->stream_id); } int q6asm_stream_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id) { return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, stream_id); } int q6asm_enc_cfg_blk_aac(struct audio_client *ac, uint32_t frames_per_buf, Loading Loading @@ -2467,12 +2532,6 @@ fail_cmd: } int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) { return q6asm_media_format_block_multi_aac(ac, cfg); } static int __q6asm_media_format_block_pcm(struct audio_client *ac, uint32_t rate, uint32_t channels, uint16_t bits_per_sample) Loading Loading @@ -2603,8 +2662,8 @@ int q6asm_media_format_block_multi_ch_pcm_v2( bits_per_sample); } int q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) static int __q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id) { struct asm_aac_fmt_blk_v2 fmt; int rc = 0; Loading @@ -2612,7 +2671,7 @@ int q6asm_media_format_block_multi_aac(struct audio_client *ac, pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, cfg->sample_rate, cfg->ch_cfg); q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE); q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id); fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - Loading Loading @@ -2646,6 +2705,24 @@ fail_cmd: return -EINVAL; } int q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) { return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id); } int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) { return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id); } int q6asm_stream_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id) { return __q6asm_media_format_block_multi_aac(ac, cfg, stream_id); } int q6asm_media_format_block_wma(struct audio_client *ac, void *cfg) { Loading Loading @@ -3630,7 +3707,7 @@ int q6asm_async_write(struct audio_client *ac, write.flags = (0x00000000 | (param->flags & 0x800000FF)); else write.flags = (0x80000000 | param->flags); write.flags |= param->last_buffer << ASM_SHIFT_LAST_BUFFER_FLAG; write.seq_id = param->uid; list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { buf_node = list_entry(ptr, struct asm_buffer_node, Loading Loading @@ -3880,7 +3957,7 @@ fail_cmd: return -EINVAL; } int q6asm_cmd(struct audio_client *ac, int cmd) static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id) { struct apr_hdr hdr; int rc; Loading @@ -3891,7 +3968,7 @@ int q6asm_cmd(struct audio_client *ac, int cmd) pr_err("APR handle NULL\n"); return -EINVAL; } q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE); q6asm_stream_add_hdr(ac, &hdr, sizeof(hdr), TRUE, stream_id); switch (cmd) { case CMD_PAUSE: pr_debug("%s:CMD_PAUSE\n", __func__); Loading Loading @@ -3969,7 +4046,18 @@ fail_cmd: return -EINVAL; } int q6asm_cmd_nowait(struct audio_client *ac, int cmd) int q6asm_cmd(struct audio_client *ac, int cmd) { return __q6asm_cmd(ac, cmd, ac->stream_id); } int q6asm_stream_cmd(struct audio_client *ac, int cmd, uint32_t stream_id) { return __q6asm_cmd(ac, cmd, stream_id); } static int __q6asm_cmd_nowait(struct audio_client *ac, int cmd, uint32_t stream_id) { struct apr_hdr hdr; int rc; Loading @@ -3978,7 +4066,7 @@ int q6asm_cmd_nowait(struct audio_client *ac, int cmd) pr_err("%s:APR handle NULL\n", __func__); return -EINVAL; } q6asm_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE); q6asm_stream_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE, stream_id); switch (cmd) { case CMD_PAUSE: pr_debug("%s:CMD_PAUSE\n", __func__); Loading @@ -3988,6 +4076,10 @@ int q6asm_cmd_nowait(struct audio_client *ac, int cmd) pr_debug("%s:CMD_EOS\n", __func__); hdr.opcode = ASM_DATA_CMD_EOS; break; case CMD_CLOSE: pr_debug("%s:CMD_CLOSE\n", __func__); hdr.opcode = ASM_STREAM_CMD_CLOSE; break; default: pr_err("%s:Invalid format[%d]\n", __func__, cmd); goto fail_cmd; Loading @@ -4008,6 +4100,54 @@ fail_cmd: return -EINVAL; } int q6asm_cmd_nowait(struct audio_client *ac, int cmd) { pr_debug("%s: stream_id: %d\n", __func__, ac->stream_id); return __q6asm_cmd_nowait(ac, cmd, ac->stream_id); } int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd, uint32_t stream_id) { pr_debug("%s: stream_id: %d\n", __func__, stream_id); return __q6asm_cmd_nowait(ac, cmd, stream_id); } int q6asm_send_meta_data(struct audio_client *ac, uint32_t initial_samples, uint32_t trailing_samples) { struct asm_data_cmd_remove_silence silence; int rc = 0; if (!ac || ac->apr == NULL) { pr_err("APR handle NULL\n"); return -EINVAL; } pr_debug("%s session[%d]", __func__, ac->session); q6asm_add_hdr_async(ac, &silence.hdr, sizeof(silence), FALSE); silence.hdr.opcode = ASM_DATA_CMD_REMOVE_INITIAL_SILENCE; silence.num_samples_to_remove = initial_samples; rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("Commmand silence failed[%d]", rc); goto fail_cmd; } silence.hdr.opcode = ASM_DATA_CMD_REMOVE_TRAILING_SILENCE; silence.num_samples_to_remove = trailing_samples; rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("Commmand silence failed[%d]", rc); goto fail_cmd; } return 0; fail_cmd: return -EINVAL; } static void q6asm_reset_buf_state(struct audio_client *ac) { int cnt = 0; Loading Loading @@ -4067,6 +4207,35 @@ fail_cmd: return -EINVAL; } int q6asm_reg_rx_underflow(struct audio_client *ac, uint16_t enable) { struct asm_session_cmd_rgstr_rx_underflow rx_underflow; int rc; if (!ac || ac->apr == NULL) { pr_err("APR handle NULL\n"); return -EINVAL; } pr_debug("%s:session[%d]enable[%d]\n", __func__, ac->session, enable); q6asm_add_hdr_async(ac, &rx_underflow.hdr, sizeof(rx_underflow), FALSE); rx_underflow.hdr.opcode = ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS; /* tx overflow event: enable */ rx_underflow.enable_flag = enable; rc = apr_send_pkt(ac->apr, (uint32_t *) &rx_underflow); if (rc < 0) { pr_err("tx overflow op[0x%x]rc[%d]\n", rx_underflow.hdr.opcode, rc); goto fail_cmd; } return 0; fail_cmd: return -EINVAL; } int q6asm_get_apr_service_id(int session_id) { pr_debug("%s\n", __func__); Loading Loading
include/sound/apr_audio-v2.h +19 −0 Original line number Diff line number Diff line Loading @@ -4729,6 +4729,25 @@ struct asm_stream_cmd_open_write_compressed { } __packed; /* Indicates the number of samples per channel to be removed from the beginning of the stream. */ #define ASM_DATA_CMD_REMOVE_INITIAL_SILENCE 0x00010D67 /* Indicates the number of samples per channel to be removed from the end of the stream. */ #define ASM_DATA_CMD_REMOVE_TRAILING_SILENCE 0x00010D68 struct asm_data_cmd_remove_silence { struct apr_hdr hdr; u32 num_samples_to_remove; /**< Number of samples per channel to be removed. @values 0 to (2@sscr{32}-1) */ } __packed; #define ASM_STREAM_CMD_OPEN_READ_COMPRESSED 0x00010D95 struct asm_stream_cmd_open_read_compressed { Loading
include/sound/q6asm-v2.h +27 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,9 @@ #define SESSION_MAX 0x08 #define ASM_CONTROL_SESSION 0x0F #define ASM_SHIFT_GAPLESS_MODE_FLAG 31 #define ASM_SHIFT_LAST_BUFFER_FLAG 30 /* payload structure bytes */ #define READDONE_IDX_STATUS 0 #define READDONE_IDX_BUFADD_LSW 1 Loading Loading @@ -131,6 +134,7 @@ struct audio_aio_write_param { uint32_t msw_ts; uint32_t flags; uint32_t metadata_len; uint32_t last_buffer; }; struct audio_aio_read_param { Loading Loading @@ -163,12 +167,14 @@ struct audio_client { uint64_t time_stamp; struct apr_svc *apr; struct apr_svc *mmap_apr; struct apr_svc *apr2; struct mutex cmd_lock; /* idx:1 out port, 0: in port*/ struct audio_port_data port[2]; wait_queue_head_t cmd_wait; wait_queue_head_t time_wait; bool perf_mode; int stream_id; /* audio cache operations fptr*/ int (*fptr_cache_ops)(struct audio_buffer *abuff, int cache_op); }; Loading Loading @@ -204,6 +210,10 @@ int q6asm_open_write(struct audio_client *ac, uint32_t format int q6asm_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample); int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode); int q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format, uint32_t wr_format); Loading Loading @@ -240,12 +250,22 @@ int q6asm_run(struct audio_client *ac, uint32_t flags, int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts); int q6asm_stream_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id); int q6asm_reg_tx_overflow(struct audio_client *ac, uint16_t enable); int q6asm_reg_rx_underflow(struct audio_client *ac, uint16_t enable); int q6asm_cmd(struct audio_client *ac, int cmd); int q6asm_stream_cmd(struct audio_client *ac, int cmd, uint32_t stream_id); int q6asm_cmd_nowait(struct audio_client *ac, int cmd); int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd, uint32_t stream_id); void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size, uint32_t *idx); Loading Loading @@ -317,6 +337,9 @@ int q6asm_media_format_block_multi_ch_pcm_v2( int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg); int q6asm_stream_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id); int q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg); Loading Loading @@ -364,4 +387,8 @@ int q6asm_get_apr_service_id(int session_id); */ int q6asm_media_format_block(struct audio_client *ac, uint32_t format); /* Send the meta data to remove initial and trailing silence */ int q6asm_send_meta_data(struct audio_client *ac, uint32_t initial_samples, uint32_t trailing_samples); #endif /* __Q6_ASM_H__ */
sound/soc/msm/qdsp6v2/q6asm.c +204 −35 Original line number Diff line number Diff line Loading @@ -811,6 +811,10 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv) (apr_fn)q6asm_callback,\ ((ac->session) << 8 | 0x0001),\ ac); ac->apr2 = apr_register("ADSP", "ASM", (apr_fn)q6asm_callback, ((ac->session) << 8 | 0x0002), ac); if (ac->apr == NULL) { pr_err("%s Registration with APR failed\n", __func__); Loading Loading @@ -1210,7 +1214,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) data->token, data->payload_size, data->src_port, data->dest_port); if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) && (data->opcode != ASM_DATA_EVENT_EOS)) (data->opcode != ASM_DATA_EVENT_EOS) && (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) pr_debug("%s:Payload = [0x%x] status[0x%x]\n", __func__, payload[0], payload[1]); if (data->opcode == APR_BASIC_RSP_RESULT) { Loading Loading @@ -1244,6 +1249,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: case ASM_CMD_ADD_TOPOLOGIES: case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS: pr_debug("%s:Payload = [0x%x]stat[0x%x]\n", __func__, payload[0], payload[1]); if (atomic_read(&ac->cmd_state) && wakeup_flag) { Loading Loading @@ -1367,7 +1375,10 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) __func__, data->opcode); break; case ASM_SESSION_EVENTX_OVERFLOW: pr_err("ASM_SESSION_EVENTX_OVERFLOW\n"); pr_debug("ASM_SESSION_EVENTX_OVERFLOW\n"); break; case ASM_SESSION_EVENT_RX_UNDERFLOW: pr_debug("ASM_SESSION_EVENT_RX_UNDERFLOW\n"); break; case ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3: pr_debug("%s: ASM_SESSION_CMDRSP_GET_SESSIONTIME_V3, payload[0] = %d, payload[1] = %d, payload[2] = %d\n", Loading Loading @@ -1519,11 +1530,11 @@ int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac) return ret; } static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg) static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id) { pr_debug("%s:pkt_size=%d cmd_flg=%d session=%d\n", __func__, pkt_size, cmd_flg, ac->session); pr_debug("%s:pkt_size=%d cmd_flg=%d session=%d stream_id=%d\n", __func__, pkt_size, cmd_flg, ac->session, stream_id); if (ac->apr == NULL) { pr_err("%s: ac->apr is NULL", __func__); return; Loading @@ -1537,8 +1548,8 @@ static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, hdr->src_domain = APR_DOMAIN_APPS; hdr->dest_svc = APR_SVC_ASM; hdr->dest_domain = APR_DOMAIN_ADSP; hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); if (cmd_flg) { hdr->token = ac->session; atomic_set(&ac->cmd_state, 1); Loading @@ -1548,11 +1559,25 @@ static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, return; } static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, static void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg) { pr_debug("pkt_size = %d, cmd_flg = %d, session = %d\n", pkt_size, cmd_flg, ac->session); __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, ac->stream_id); return; } static void q6asm_stream_add_hdr(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, int32_t stream_id) { __q6asm_add_hdr(ac, hdr, pkt_size, cmd_flg, stream_id); return; } static void __q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id) { pr_debug("%s pkt_size = %d, cmd_flg = %d, session = %d stream_id=%d\n", __func__, pkt_size, cmd_flg, ac->session, stream_id); hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \ APR_HDR_LEN(sizeof(struct apr_hdr)),\ APR_PKT_VER); Loading @@ -1564,8 +1589,8 @@ static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, hdr->src_domain = APR_DOMAIN_APPS; hdr->dest_svc = APR_SVC_ASM; hdr->dest_domain = APR_DOMAIN_ADSP; hdr->src_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->dest_port = ((ac->session << 8) & 0xFF00) | 0x01; hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id+1); if (cmd_flg) { hdr->token = ac->session; atomic_set(&ac->cmd_state, 1); Loading @@ -1574,6 +1599,21 @@ static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, return; } static void q6asm_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg) { __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg, ac->stream_id); return; } static void q6asm_stream_add_hdr_async(struct audio_client *ac, struct apr_hdr *hdr, uint32_t pkt_size, uint32_t cmd_flg, int32_t stream_id) { __q6asm_add_hdr_async(ac, hdr, pkt_size, cmd_flg, stream_id); return; } static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr, u32 pkt_size, u32 cmd_flg, u32 token) { Loading Loading @@ -1682,7 +1722,8 @@ int q6asm_open_read_v2(struct audio_client *ac, uint32_t format, } static int __q6asm_open_write(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) uint16_t bits_per_sample, uint32_t stream_id, bool is_gapless_mode) { int rc = 0x00; struct asm_stream_cmd_open_write_v3 open; Loading @@ -1694,14 +1735,17 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session, format); q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE); q6asm_stream_add_hdr(ac, &open.hdr, sizeof(open), TRUE, stream_id); open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3; open.mode_flags = 0x00; if (ac->perf_mode) open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION; else else { open.mode_flags |= ASM_LEGACY_STREAM_SESSION; if (is_gapless_mode) open.mode_flags |= 1 << ASM_SHIFT_GAPLESS_MODE_FLAG; } /* source endpoint : matrix */ open.sink_endpointype = ASM_END_POINT_DEVICE_MATRIX; Loading Loading @@ -1760,13 +1804,23 @@ fail_cmd: int q6asm_open_write(struct audio_client *ac, uint32_t format) { return __q6asm_open_write(ac, format, 16); return __q6asm_open_write(ac, format, 16, ac->stream_id, false /*gapless*/); } int q6asm_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) { return __q6asm_open_write(ac, format, bits_per_sample); return __q6asm_open_write(ac, format, bits_per_sample, ac->stream_id, false /*gapless*/); } int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode) { return __q6asm_open_write(ac, format, bits_per_sample, stream_id, is_gapless_mode); } int q6asm_open_read_write(struct audio_client *ac, Loading Loading @@ -1920,8 +1974,8 @@ fail_cmd: return -EINVAL; } int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts) static int __q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id) { struct asm_session_cmd_run_v2 run; int rc; Loading @@ -1930,7 +1984,7 @@ int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, return -EINVAL; } pr_debug("session[%d]", ac->session); q6asm_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE); q6asm_stream_add_hdr_async(ac, &run.hdr, sizeof(run), TRUE, stream_id); run.hdr.opcode = ASM_SESSION_CMD_RUN_V2; run.flags = flags; Loading @@ -1948,6 +2002,17 @@ int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, return 0; } int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts) { return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, ac->stream_id); } int q6asm_stream_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts, uint32_t stream_id) { return __q6asm_run_nowait(ac, flags, msw_ts, lsw_ts, stream_id); } int q6asm_enc_cfg_blk_aac(struct audio_client *ac, uint32_t frames_per_buf, Loading Loading @@ -2467,12 +2532,6 @@ fail_cmd: } int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) { return q6asm_media_format_block_multi_aac(ac, cfg); } static int __q6asm_media_format_block_pcm(struct audio_client *ac, uint32_t rate, uint32_t channels, uint16_t bits_per_sample) Loading Loading @@ -2603,8 +2662,8 @@ int q6asm_media_format_block_multi_ch_pcm_v2( bits_per_sample); } int q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) static int __q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id) { struct asm_aac_fmt_blk_v2 fmt; int rc = 0; Loading @@ -2612,7 +2671,7 @@ int q6asm_media_format_block_multi_aac(struct audio_client *ac, pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, cfg->sample_rate, cfg->ch_cfg); q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE); q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id); fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - Loading Loading @@ -2646,6 +2705,24 @@ fail_cmd: return -EINVAL; } int q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) { return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id); } int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg) { return __q6asm_media_format_block_multi_aac(ac, cfg, ac->stream_id); } int q6asm_stream_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id) { return __q6asm_media_format_block_multi_aac(ac, cfg, stream_id); } int q6asm_media_format_block_wma(struct audio_client *ac, void *cfg) { Loading Loading @@ -3630,7 +3707,7 @@ int q6asm_async_write(struct audio_client *ac, write.flags = (0x00000000 | (param->flags & 0x800000FF)); else write.flags = (0x80000000 | param->flags); write.flags |= param->last_buffer << ASM_SHIFT_LAST_BUFFER_FLAG; write.seq_id = param->uid; list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { buf_node = list_entry(ptr, struct asm_buffer_node, Loading Loading @@ -3880,7 +3957,7 @@ fail_cmd: return -EINVAL; } int q6asm_cmd(struct audio_client *ac, int cmd) static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id) { struct apr_hdr hdr; int rc; Loading @@ -3891,7 +3968,7 @@ int q6asm_cmd(struct audio_client *ac, int cmd) pr_err("APR handle NULL\n"); return -EINVAL; } q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE); q6asm_stream_add_hdr(ac, &hdr, sizeof(hdr), TRUE, stream_id); switch (cmd) { case CMD_PAUSE: pr_debug("%s:CMD_PAUSE\n", __func__); Loading Loading @@ -3969,7 +4046,18 @@ fail_cmd: return -EINVAL; } int q6asm_cmd_nowait(struct audio_client *ac, int cmd) int q6asm_cmd(struct audio_client *ac, int cmd) { return __q6asm_cmd(ac, cmd, ac->stream_id); } int q6asm_stream_cmd(struct audio_client *ac, int cmd, uint32_t stream_id) { return __q6asm_cmd(ac, cmd, stream_id); } static int __q6asm_cmd_nowait(struct audio_client *ac, int cmd, uint32_t stream_id) { struct apr_hdr hdr; int rc; Loading @@ -3978,7 +4066,7 @@ int q6asm_cmd_nowait(struct audio_client *ac, int cmd) pr_err("%s:APR handle NULL\n", __func__); return -EINVAL; } q6asm_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE); q6asm_stream_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE, stream_id); switch (cmd) { case CMD_PAUSE: pr_debug("%s:CMD_PAUSE\n", __func__); Loading @@ -3988,6 +4076,10 @@ int q6asm_cmd_nowait(struct audio_client *ac, int cmd) pr_debug("%s:CMD_EOS\n", __func__); hdr.opcode = ASM_DATA_CMD_EOS; break; case CMD_CLOSE: pr_debug("%s:CMD_CLOSE\n", __func__); hdr.opcode = ASM_STREAM_CMD_CLOSE; break; default: pr_err("%s:Invalid format[%d]\n", __func__, cmd); goto fail_cmd; Loading @@ -4008,6 +4100,54 @@ fail_cmd: return -EINVAL; } int q6asm_cmd_nowait(struct audio_client *ac, int cmd) { pr_debug("%s: stream_id: %d\n", __func__, ac->stream_id); return __q6asm_cmd_nowait(ac, cmd, ac->stream_id); } int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd, uint32_t stream_id) { pr_debug("%s: stream_id: %d\n", __func__, stream_id); return __q6asm_cmd_nowait(ac, cmd, stream_id); } int q6asm_send_meta_data(struct audio_client *ac, uint32_t initial_samples, uint32_t trailing_samples) { struct asm_data_cmd_remove_silence silence; int rc = 0; if (!ac || ac->apr == NULL) { pr_err("APR handle NULL\n"); return -EINVAL; } pr_debug("%s session[%d]", __func__, ac->session); q6asm_add_hdr_async(ac, &silence.hdr, sizeof(silence), FALSE); silence.hdr.opcode = ASM_DATA_CMD_REMOVE_INITIAL_SILENCE; silence.num_samples_to_remove = initial_samples; rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("Commmand silence failed[%d]", rc); goto fail_cmd; } silence.hdr.opcode = ASM_DATA_CMD_REMOVE_TRAILING_SILENCE; silence.num_samples_to_remove = trailing_samples; rc = apr_send_pkt(ac->apr, (uint32_t *) &silence); if (rc < 0) { pr_err("Commmand silence failed[%d]", rc); goto fail_cmd; } return 0; fail_cmd: return -EINVAL; } static void q6asm_reset_buf_state(struct audio_client *ac) { int cnt = 0; Loading Loading @@ -4067,6 +4207,35 @@ fail_cmd: return -EINVAL; } int q6asm_reg_rx_underflow(struct audio_client *ac, uint16_t enable) { struct asm_session_cmd_rgstr_rx_underflow rx_underflow; int rc; if (!ac || ac->apr == NULL) { pr_err("APR handle NULL\n"); return -EINVAL; } pr_debug("%s:session[%d]enable[%d]\n", __func__, ac->session, enable); q6asm_add_hdr_async(ac, &rx_underflow.hdr, sizeof(rx_underflow), FALSE); rx_underflow.hdr.opcode = ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS; /* tx overflow event: enable */ rx_underflow.enable_flag = enable; rc = apr_send_pkt(ac->apr, (uint32_t *) &rx_underflow); if (rc < 0) { pr_err("tx overflow op[0x%x]rc[%d]\n", rx_underflow.hdr.opcode, rc); goto fail_cmd; } return 0; fail_cmd: return -EINVAL; } int q6asm_get_apr_service_id(int session_id) { pr_debug("%s\n", __func__); Loading