Loading dsp/q6afe.c +175 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,21 @@ #define WAKELOCK_TIMEOUT 5000 #define AFE_CLK_TOKEN 1024 struct afe_avcs_payload_port_mapping { u16 port_id; struct avcs_load_unload_modules_payload *payload; } __packed; enum { ENCODER_CASE, DECODER_CASE, /* Add new use case here */ MAX_ALLOWED_USE_CASES }; static struct afe_avcs_payload_port_mapping *pm[MAX_ALLOWED_USE_CASES]; enum { AFE_COMMON_RX_CAL = 0, AFE_COMMON_TX_CAL, Loading Loading @@ -240,6 +255,124 @@ static bool proxy_afe_started = false; #define SIZEOF_CFG_CMD(y) \ (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y))) static void q6afe_unload_avcs_modules(u16 port_id, int index) { int ret = 0; ret = q6core_avcs_load_unload_modules(pm[index]->payload, AVCS_UNLOAD_MODULES); if (ret < 0) pr_err("%s: avcs module unload failed %d\n", __func__, ret); kfree(pm[index]->payload); pm[index]->payload = NULL; kfree(pm[index]); pm[index] = NULL; } static int q6afe_load_avcs_modules(int num_modules, u16 port_id, uint32_t use_case, u32 format_id) { int i = 0; int32_t ret = 0; size_t payload_size = 0, port_struct_size = 0; struct afe_avcs_payload_port_mapping payload_map; struct avcs_load_unload_modules_sec_payload sec_payload; if (num_modules <= 0) { pr_err("%s: Invalid number of modules to load\n"); return -EINVAL; } for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) { if (pm[i] == NULL) { port_struct_size = sizeof(payload_map); pm[i] = kzalloc(port_struct_size, GFP_KERNEL); if (!pm[i]) return -ENOMEM; pm[i]->port_id = port_id; payload_size = sizeof(uint32_t) + (sizeof(sec_payload) * num_modules); pm[i]->payload = kzalloc(payload_size, GFP_KERNEL); if (!pm[i]->payload) { kfree(pm[i]); pm[i] = NULL; return -ENOMEM; } /* * index 0 : packetizer/de-packetizer * index 1 : encoder/decoder */ pm[i]->payload->num_modules = num_modules; /* * Remaining fields of payload * are initialized to zero */ if (use_case == ENCODER_CASE) { pm[i]->payload->load_unload_info[0].module_type = AMDB_MODULE_TYPE_PACKETIZER; pm[i]->payload->load_unload_info[0].id1 = AVS_MODULE_ID_PACKETIZER_COP; pm[i]->payload->load_unload_info[1].module_type = AMDB_MODULE_TYPE_ENCODER; pm[i]->payload->load_unload_info[1].id1 = format_id; } else if (use_case == DECODER_CASE) { pm[i]->payload->load_unload_info[0].module_type = AMDB_MODULE_TYPE_DEPACKETIZER; pm[i]->payload->load_unload_info[0].id1 = AVS_MODULE_ID_DEPACKETIZER_COP_V1; if (format_id == ENC_CODEC_TYPE_LDAC) { pm[i]->payload->load_unload_info[0].id1 = AVS_MODULE_ID_DEPACKETIZER_COP; goto load_unload; } pm[i]->payload->load_unload_info[1].module_type = AMDB_MODULE_TYPE_DECODER; pm[i]->payload->load_unload_info[1].id1 = format_id; } else { pr_err("%s:load usecase %d not supported\n", __func__, use_case); ret = -EINVAL; goto fail; } load_unload: ret = q6core_avcs_load_unload_modules(pm[i]->payload, AVCS_LOAD_MODULES); if (ret < 0) { pr_err("%s: load failed %d\n", __func__, ret); goto fail; } return 0; } } ret = -EINVAL; if (i == MAX_ALLOWED_USE_CASES) { pr_err("%s: Not enough ports available\n", __func__); return ret; } fail: kfree(pm[i]->payload); pm[i]->payload = NULL; kfree(pm[i]); pm[i] = NULL; return ret; } static int afe_get_cal_hw_delay(int32_t path, struct audio_cal_hw_delay_entry *entry); static int remap_cal_data(struct cal_block_data *cal_block, int cal_index); Loading Loading @@ -5516,6 +5649,19 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, if (enc_cfg != NULL) { pr_debug("%s: Found AFE encoder support for SLIMBUS format = %d\n", __func__, codec_format); if ((q6core_get_avcs_api_version_per_service( APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) { ret = q6afe_load_avcs_modules(2, port_id, ENCODER_CASE, codec_format); if (ret < 0) { pr_err("%s:encoder load for port 0x%x failed %d\n", __func__, port_id, ret); goto fail_cmd; } } ret = q6afe_send_enc_config(port_id, enc_cfg, codec_format, *afe_config, afe_in_channels, Loading @@ -5530,6 +5676,23 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, if (dec_cfg != NULL) { pr_debug("%s: Found AFE decoder support for SLIMBUS format = %d\n", __func__, codec_format); if ((q6core_get_avcs_api_version_per_service( APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) { /* LDAC doesn't require decoder */ if (codec_format == ENC_CODEC_TYPE_LDAC) ret = q6afe_load_avcs_modules(1, port_id, DECODER_CASE, codec_format); else ret = q6afe_load_avcs_modules(2, port_id, DECODER_CASE, codec_format); if (ret < 0) { pr_err("%s:decoder load for port 0x%x failed %d\n", __func__, port_id, ret); goto fail_cmd; } } ret = q6afe_send_dec_config(port_id, *afe_config, dec_cfg, codec_format, afe_in_channels, Loading Loading @@ -8341,6 +8504,7 @@ int afe_close(int port_id) struct afe_port_cmd_device_stop stop; enum afe_mad_type mad_type; int ret = 0; u16 i; int index = 0; uint16_t port_index; Loading Loading @@ -8463,6 +8627,15 @@ int afe_close(int port_id) pr_err("%s: AFE close failed %d\n", __func__, ret); fail_cmd: if ((q6core_get_avcs_api_version_per_service( APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) { for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) { if (pm[i] && pm[i]->port_id == port_id) { q6afe_unload_avcs_modules(port_id, i); break; } } } mutex_unlock(&this_afe.afe_cmd_lock); return ret; } Loading dsp/q6core.c +135 −2 Original line number Diff line number Diff line Loading @@ -61,9 +61,11 @@ struct q6core_str { wait_queue_head_t cmd_req_wait; wait_queue_head_t avcs_fwk_ver_req_wait; wait_queue_head_t lpass_npa_rsc_wait; wait_queue_head_t avcs_module_load_unload_wait; u32 lpass_npa_rsc_rsp_rcvd; u32 bus_bw_resp_received; u32 mdf_map_resp_received; u32 avcs_module_resp_received; enum cmd_flags { FLAG_NONE, FLAG_CMDRSP_LICENSE_RESULT Loading @@ -87,6 +89,9 @@ struct q6core_str { static struct q6core_str q6core_lcl; /* Global payload used for AVCS_CMD_RSP_MODULES command */ static struct avcs_load_unload_modules_payload *rsp_payload; struct generic_get_data_ { int valid; int size_in_ints; Loading Loading @@ -343,6 +348,29 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) q6core_lcl.lpass_npa_rsc_rsp_rcvd = 1; wake_up(&q6core_lcl.lpass_npa_rsc_wait); break; case AVCS_CMD_LOAD_MODULES: pr_err("%s: Cmd = %s failed status[%s]\n", __func__, "AVCS_CMD_LOAD__MODULES", adsp_err_get_err_str(payload1[1])); q6core_lcl.avcs_module_resp_received = 1; q6core_lcl.adsp_status = -payload1[1]; wake_up(&q6core_lcl.avcs_module_load_unload_wait); break; case AVCS_CMD_UNLOAD_MODULES: if (payload1[1] == ADSP_EOK) { pr_debug("%s: Cmd = %s success status[%s]\n", __func__, "AVCS_CMD_UNLOAD_MODULES", "ADSP_EOK"); } else { pr_err("%s: Cmd = %s failed status[%s]\n", __func__, "AVCS_CMD_UNLOAD_MODULES", adsp_err_get_err_str(payload1[1])); q6core_lcl.adsp_status = -payload1[1]; } q6core_lcl.avcs_module_resp_received = 1; wake_up(&q6core_lcl.avcs_module_load_unload_wait); break; default: pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n", __func__, Loading Loading @@ -441,6 +469,13 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) q6core_lcl.avcs_fwk_ver_resp_received = 1; wake_up(&q6core_lcl.avcs_fwk_ver_req_wait); break; case AVCS_CMD_RSP_LOAD_MODULES: pr_debug("%s: Received AVCS_CMD_RSP_LOAD_MODULES\n", __func__); memcpy(rsp_payload, data->payload, data->payload_size); q6core_lcl.avcs_module_resp_received = 1; wake_up(&q6core_lcl.avcs_module_load_unload_wait); break; default: pr_err("%s: Message id from adsp core svc: 0x%x\n", __func__, data->opcode); Loading Loading @@ -821,7 +856,6 @@ int32_t core_get_license_status(uint32_t module_id) get_lvr_cmd.hdr.opcode = AVCS_CMD_GET_LICENSE_VALIDATION_RESULT; get_lvr_cmd.id = module_id; ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *) &get_lvr_cmd); if (ret < 0) { pr_err("%s: license_validation request failed, err %d\n", Loading Loading @@ -894,6 +928,105 @@ uint32_t core_set_dolby_manufacturer_id(int manufacturer_id) } EXPORT_SYMBOL(core_set_dolby_manufacturer_id); int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload *payload, uint32_t preload_type) { int ret = 0; size_t packet_size = 0, payload_size = 0; struct avcs_cmd_dynamic_modules *mod = NULL; int num_modules; if (payload == NULL) { pr_err("%s: payload is null\n"); return -EINVAL; } mutex_lock(&(q6core_lcl.cmd_lock)); num_modules = payload->num_modules; ocm_core_open(); if (q6core_lcl.core_handle_q == NULL) { pr_err("%s: apr registration for CORE failed\n", __func__); mutex_unlock(&(q6core_lcl.cmd_lock)); return -ENODEV; } payload_size = (sizeof(struct avcs_load_unload_modules_sec_payload) * num_modules) + sizeof(uint32_t); packet_size = sizeof(struct avcs_cmd_dynamic_modules) + payload_size - sizeof(uint32_t); mod = kzalloc(packet_size, GFP_KERNEL); if (!mod) { mutex_unlock(&(q6core_lcl.cmd_lock)); return -ENOMEM; } rsp_payload = kzalloc(payload_size, GFP_KERNEL); if (!rsp_payload) { kfree(mod); mutex_unlock(&(q6core_lcl.cmd_lock)); return -ENOMEM; } memcpy((uint8_t *)mod + sizeof(struct apr_hdr) + sizeof(struct avcs_load_unload_modules_meminfo), payload, payload_size); mod->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mod->hdr.pkt_size = packet_size; mod->hdr.src_port = 0; mod->hdr.dest_port = 0; mod->hdr.token = 0; mod->meminfo.data_payload_addr_lsw = 0; mod->meminfo.data_payload_addr_msw = 0; mod->meminfo.mem_map_handle = 0; mod->meminfo.buffer_size = payload_size; if (preload_type == AVCS_LOAD_MODULES) mod->hdr.opcode = AVCS_CMD_LOAD_MODULES; else mod->hdr.opcode = AVCS_CMD_UNLOAD_MODULES; q6core_lcl.avcs_module_resp_received = 0; ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *)mod); if (ret < 0) { pr_err("%s: modules load/unload failed ret = %d\n", __func__, ret); goto done; } ret = wait_event_timeout(q6core_lcl.avcs_module_load_unload_wait, (q6core_lcl.avcs_module_resp_received == 1), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s wait event timeout for avcs load/unload module\n", __func__); ret = -ETIMEDOUT; goto done; } if (q6core_lcl.adsp_status < 0) { pr_err("%s: modules load/unload failed %d\n", __func__, q6core_lcl.adsp_status); ret = q6core_lcl.adsp_status; goto done; } else { if (mod->hdr.opcode == AVCS_CMD_LOAD_MODULES) memcpy(payload, rsp_payload, payload_size); } done: kfree(mod); kfree(rsp_payload); mutex_unlock(&(q6core_lcl.cmd_lock)); return ret; } EXPORT_SYMBOL(q6core_avcs_load_unload_modules); int32_t q6core_load_unload_topo_modules(uint32_t topo_id, bool preload_type) { Loading Loading @@ -1871,7 +2004,6 @@ static int q6core_probe(struct platform_device *pdev) if (rc < 0) goto err; q6core_lcl.avs_state = avs_state; rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); if (rc) { dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", Loading Loading @@ -1926,6 +2058,7 @@ int __init core_init(void) init_waitqueue_head(&q6core_lcl.avcs_fwk_ver_req_wait); init_waitqueue_head(&q6core_lcl.mdf_map_resp_wait); init_waitqueue_head(&q6core_lcl.lpass_npa_rsc_wait); init_waitqueue_head(&q6core_lcl.avcs_module_load_unload_wait); q6core_lcl.cmd_resp_received_flag = FLAG_NONE; mutex_init(&q6core_lcl.cmd_lock); mutex_init(&q6core_lcl.ver_lock); Loading include/dsp/apr_audio-v2.h +10 −0 Original line number Diff line number Diff line Loading @@ -4143,6 +4143,16 @@ struct afe_id_aptx_adaptive_enc_init #define AFE_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AFE_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 /* Macros for dynamic loading of modules by AVCS */ #define AVS_MODULE_ID_PACKETIZER_COP 0x0001322A #define AVS_MODULE_ID_PACKETIZER_COP_V1 0x000132E8 #define AVS_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AVS_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 /* * Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module. * This parameter cannot be set runtime. Loading include/dsp/q6core.h +121 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #define AVCS_CMD_ADSP_EVENT_GET_STATE 0x0001290C #define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D #define AVCS_API_VERSION_V4 4 #define AVCS_API_VERSION_V5 5 #define APRV2_IDS_SERVICE_ID_ADSP_CORE_V (0x3) bool q6core_is_adsp_ready(void); Loading Loading @@ -198,6 +199,126 @@ struct avcs_cmd_load_unload_topo_modules { uint32_t topology_id; } __packed; #define AVCS_LOAD_MODULES 1 #define AVCS_UNLOAD_MODULES 0 #define AVCS_CMD_LOAD_MODULES 0x00012989 #define AVCS_CMD_UNLOAD_MODULES 0x0001298A #define AVCS_CMD_RSP_LOAD_MODULES 0x0001298B /* * Module is generic, such as a preprocessor, * postprocessor, or volume control * module. */ #define AMDB_MODULE_TYPE_GENERIC 0 /** Module is a decoder. */ #define AMDB_MODULE_TYPE_DECODER 1 /** Module is an encoder. */ #define AMDB_MODULE_TYPE_ENCODER 2 /** Module is a converter. */ #define AMDB_MODULE_TYPE_CONVERTER 3 /** Module is a packetizer. */ #define AMDB_MODULE_TYPE_PACKETIZER 4 /** Module is a depacketizer. */ #define AMDB_MODULE_TYPE_DEPACKETIZER 5 struct avcs_load_unload_modules_sec_payload { uint32_t module_type; /* * < Type of module. * @values * - #AMDB_MODULE_TYPE_GENERIC * - #AMDB_MODULE_TYPE_DECODER * - #AMDB_MODULE_TYPE_ENCODER * - #AMDB_MODULE_TYPE_CONVERTER * - #AMDB_MODULE_TYPE_PACKETIZER * - #AMDB_MODULE_TYPE_DEPACKETIZER */ uint32_t id1; /* * < One of the following types of IDs: * - Format ID for the encoder, decoder, and packetizer module types * - Module ID for the generic module type * - Source format ID for the converter module type */ uint32_t id2; /* * < Sink format ID for the converter module type. * Zero for other module types */ uint32_t handle_lsw; /* < LSW of the Handle to the module loaded */ uint32_t handle_msw; /* < MSW of the Handle to the module loaded. */ } __packed; struct avcs_load_unload_modules_payload { uint32_t num_modules; /**< Number of modules being registered */ struct avcs_load_unload_modules_sec_payload load_unload_info[0]; /* * < Load/unload information for num_modules. * It will be of type avcs_load_unload_info_t[num_modules] */ } __packed; struct avcs_load_unload_modules_meminfo { uint32_t data_payload_addr_lsw; /**< Lower 32 bits of the 64-bit data payload address. */ uint32_t data_payload_addr_msw; /**< Upper 32 bits of the 64-bit data payload address. */ uint32_t mem_map_handle; /* * < Unique identifier for an address. The aDSP returns this memory map * handle through the #AVCS_CMD_SHARED_MEM_MAP_REGIONS command. * @values @vertspace{-2} * - NULL -- Parameter data payloads are within the message payload * (in-band). * - Non-NULL -- Parameter data payloads begin at the address specified * in the data_payload_addr_lsw and data_payload_addr_msw fields * (out-of-band). * The client can choose in-band or out-of-band */ uint32_t buffer_size; /* * < Actual size (in bytes) of the valid data * in the data payload address. */ } __packed; struct avcs_cmd_dynamic_modules { struct apr_hdr hdr; struct avcs_load_unload_modules_meminfo meminfo; struct avcs_load_unload_modules_payload payload; } __packed; int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload *payload, uint32_t preload_type); /* This command allows a remote client(HLOS) creates a client to LPASS NPA * resource node. Currently, this command supports only the NPA Sleep resource * "/island/core/drivers" node ID. Loading Loading
dsp/q6afe.c +175 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,21 @@ #define WAKELOCK_TIMEOUT 5000 #define AFE_CLK_TOKEN 1024 struct afe_avcs_payload_port_mapping { u16 port_id; struct avcs_load_unload_modules_payload *payload; } __packed; enum { ENCODER_CASE, DECODER_CASE, /* Add new use case here */ MAX_ALLOWED_USE_CASES }; static struct afe_avcs_payload_port_mapping *pm[MAX_ALLOWED_USE_CASES]; enum { AFE_COMMON_RX_CAL = 0, AFE_COMMON_TX_CAL, Loading Loading @@ -240,6 +255,124 @@ static bool proxy_afe_started = false; #define SIZEOF_CFG_CMD(y) \ (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y))) static void q6afe_unload_avcs_modules(u16 port_id, int index) { int ret = 0; ret = q6core_avcs_load_unload_modules(pm[index]->payload, AVCS_UNLOAD_MODULES); if (ret < 0) pr_err("%s: avcs module unload failed %d\n", __func__, ret); kfree(pm[index]->payload); pm[index]->payload = NULL; kfree(pm[index]); pm[index] = NULL; } static int q6afe_load_avcs_modules(int num_modules, u16 port_id, uint32_t use_case, u32 format_id) { int i = 0; int32_t ret = 0; size_t payload_size = 0, port_struct_size = 0; struct afe_avcs_payload_port_mapping payload_map; struct avcs_load_unload_modules_sec_payload sec_payload; if (num_modules <= 0) { pr_err("%s: Invalid number of modules to load\n"); return -EINVAL; } for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) { if (pm[i] == NULL) { port_struct_size = sizeof(payload_map); pm[i] = kzalloc(port_struct_size, GFP_KERNEL); if (!pm[i]) return -ENOMEM; pm[i]->port_id = port_id; payload_size = sizeof(uint32_t) + (sizeof(sec_payload) * num_modules); pm[i]->payload = kzalloc(payload_size, GFP_KERNEL); if (!pm[i]->payload) { kfree(pm[i]); pm[i] = NULL; return -ENOMEM; } /* * index 0 : packetizer/de-packetizer * index 1 : encoder/decoder */ pm[i]->payload->num_modules = num_modules; /* * Remaining fields of payload * are initialized to zero */ if (use_case == ENCODER_CASE) { pm[i]->payload->load_unload_info[0].module_type = AMDB_MODULE_TYPE_PACKETIZER; pm[i]->payload->load_unload_info[0].id1 = AVS_MODULE_ID_PACKETIZER_COP; pm[i]->payload->load_unload_info[1].module_type = AMDB_MODULE_TYPE_ENCODER; pm[i]->payload->load_unload_info[1].id1 = format_id; } else if (use_case == DECODER_CASE) { pm[i]->payload->load_unload_info[0].module_type = AMDB_MODULE_TYPE_DEPACKETIZER; pm[i]->payload->load_unload_info[0].id1 = AVS_MODULE_ID_DEPACKETIZER_COP_V1; if (format_id == ENC_CODEC_TYPE_LDAC) { pm[i]->payload->load_unload_info[0].id1 = AVS_MODULE_ID_DEPACKETIZER_COP; goto load_unload; } pm[i]->payload->load_unload_info[1].module_type = AMDB_MODULE_TYPE_DECODER; pm[i]->payload->load_unload_info[1].id1 = format_id; } else { pr_err("%s:load usecase %d not supported\n", __func__, use_case); ret = -EINVAL; goto fail; } load_unload: ret = q6core_avcs_load_unload_modules(pm[i]->payload, AVCS_LOAD_MODULES); if (ret < 0) { pr_err("%s: load failed %d\n", __func__, ret); goto fail; } return 0; } } ret = -EINVAL; if (i == MAX_ALLOWED_USE_CASES) { pr_err("%s: Not enough ports available\n", __func__); return ret; } fail: kfree(pm[i]->payload); pm[i]->payload = NULL; kfree(pm[i]); pm[i] = NULL; return ret; } static int afe_get_cal_hw_delay(int32_t path, struct audio_cal_hw_delay_entry *entry); static int remap_cal_data(struct cal_block_data *cal_block, int cal_index); Loading Loading @@ -5516,6 +5649,19 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, if (enc_cfg != NULL) { pr_debug("%s: Found AFE encoder support for SLIMBUS format = %d\n", __func__, codec_format); if ((q6core_get_avcs_api_version_per_service( APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) { ret = q6afe_load_avcs_modules(2, port_id, ENCODER_CASE, codec_format); if (ret < 0) { pr_err("%s:encoder load for port 0x%x failed %d\n", __func__, port_id, ret); goto fail_cmd; } } ret = q6afe_send_enc_config(port_id, enc_cfg, codec_format, *afe_config, afe_in_channels, Loading @@ -5530,6 +5676,23 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, if (dec_cfg != NULL) { pr_debug("%s: Found AFE decoder support for SLIMBUS format = %d\n", __func__, codec_format); if ((q6core_get_avcs_api_version_per_service( APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) { /* LDAC doesn't require decoder */ if (codec_format == ENC_CODEC_TYPE_LDAC) ret = q6afe_load_avcs_modules(1, port_id, DECODER_CASE, codec_format); else ret = q6afe_load_avcs_modules(2, port_id, DECODER_CASE, codec_format); if (ret < 0) { pr_err("%s:decoder load for port 0x%x failed %d\n", __func__, port_id, ret); goto fail_cmd; } } ret = q6afe_send_dec_config(port_id, *afe_config, dec_cfg, codec_format, afe_in_channels, Loading Loading @@ -8341,6 +8504,7 @@ int afe_close(int port_id) struct afe_port_cmd_device_stop stop; enum afe_mad_type mad_type; int ret = 0; u16 i; int index = 0; uint16_t port_index; Loading Loading @@ -8463,6 +8627,15 @@ int afe_close(int port_id) pr_err("%s: AFE close failed %d\n", __func__, ret); fail_cmd: if ((q6core_get_avcs_api_version_per_service( APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) { for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) { if (pm[i] && pm[i]->port_id == port_id) { q6afe_unload_avcs_modules(port_id, i); break; } } } mutex_unlock(&this_afe.afe_cmd_lock); return ret; } Loading
dsp/q6core.c +135 −2 Original line number Diff line number Diff line Loading @@ -61,9 +61,11 @@ struct q6core_str { wait_queue_head_t cmd_req_wait; wait_queue_head_t avcs_fwk_ver_req_wait; wait_queue_head_t lpass_npa_rsc_wait; wait_queue_head_t avcs_module_load_unload_wait; u32 lpass_npa_rsc_rsp_rcvd; u32 bus_bw_resp_received; u32 mdf_map_resp_received; u32 avcs_module_resp_received; enum cmd_flags { FLAG_NONE, FLAG_CMDRSP_LICENSE_RESULT Loading @@ -87,6 +89,9 @@ struct q6core_str { static struct q6core_str q6core_lcl; /* Global payload used for AVCS_CMD_RSP_MODULES command */ static struct avcs_load_unload_modules_payload *rsp_payload; struct generic_get_data_ { int valid; int size_in_ints; Loading Loading @@ -343,6 +348,29 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) q6core_lcl.lpass_npa_rsc_rsp_rcvd = 1; wake_up(&q6core_lcl.lpass_npa_rsc_wait); break; case AVCS_CMD_LOAD_MODULES: pr_err("%s: Cmd = %s failed status[%s]\n", __func__, "AVCS_CMD_LOAD__MODULES", adsp_err_get_err_str(payload1[1])); q6core_lcl.avcs_module_resp_received = 1; q6core_lcl.adsp_status = -payload1[1]; wake_up(&q6core_lcl.avcs_module_load_unload_wait); break; case AVCS_CMD_UNLOAD_MODULES: if (payload1[1] == ADSP_EOK) { pr_debug("%s: Cmd = %s success status[%s]\n", __func__, "AVCS_CMD_UNLOAD_MODULES", "ADSP_EOK"); } else { pr_err("%s: Cmd = %s failed status[%s]\n", __func__, "AVCS_CMD_UNLOAD_MODULES", adsp_err_get_err_str(payload1[1])); q6core_lcl.adsp_status = -payload1[1]; } q6core_lcl.avcs_module_resp_received = 1; wake_up(&q6core_lcl.avcs_module_load_unload_wait); break; default: pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n", __func__, Loading Loading @@ -441,6 +469,13 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) q6core_lcl.avcs_fwk_ver_resp_received = 1; wake_up(&q6core_lcl.avcs_fwk_ver_req_wait); break; case AVCS_CMD_RSP_LOAD_MODULES: pr_debug("%s: Received AVCS_CMD_RSP_LOAD_MODULES\n", __func__); memcpy(rsp_payload, data->payload, data->payload_size); q6core_lcl.avcs_module_resp_received = 1; wake_up(&q6core_lcl.avcs_module_load_unload_wait); break; default: pr_err("%s: Message id from adsp core svc: 0x%x\n", __func__, data->opcode); Loading Loading @@ -821,7 +856,6 @@ int32_t core_get_license_status(uint32_t module_id) get_lvr_cmd.hdr.opcode = AVCS_CMD_GET_LICENSE_VALIDATION_RESULT; get_lvr_cmd.id = module_id; ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *) &get_lvr_cmd); if (ret < 0) { pr_err("%s: license_validation request failed, err %d\n", Loading Loading @@ -894,6 +928,105 @@ uint32_t core_set_dolby_manufacturer_id(int manufacturer_id) } EXPORT_SYMBOL(core_set_dolby_manufacturer_id); int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload *payload, uint32_t preload_type) { int ret = 0; size_t packet_size = 0, payload_size = 0; struct avcs_cmd_dynamic_modules *mod = NULL; int num_modules; if (payload == NULL) { pr_err("%s: payload is null\n"); return -EINVAL; } mutex_lock(&(q6core_lcl.cmd_lock)); num_modules = payload->num_modules; ocm_core_open(); if (q6core_lcl.core_handle_q == NULL) { pr_err("%s: apr registration for CORE failed\n", __func__); mutex_unlock(&(q6core_lcl.cmd_lock)); return -ENODEV; } payload_size = (sizeof(struct avcs_load_unload_modules_sec_payload) * num_modules) + sizeof(uint32_t); packet_size = sizeof(struct avcs_cmd_dynamic_modules) + payload_size - sizeof(uint32_t); mod = kzalloc(packet_size, GFP_KERNEL); if (!mod) { mutex_unlock(&(q6core_lcl.cmd_lock)); return -ENOMEM; } rsp_payload = kzalloc(payload_size, GFP_KERNEL); if (!rsp_payload) { kfree(mod); mutex_unlock(&(q6core_lcl.cmd_lock)); return -ENOMEM; } memcpy((uint8_t *)mod + sizeof(struct apr_hdr) + sizeof(struct avcs_load_unload_modules_meminfo), payload, payload_size); mod->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mod->hdr.pkt_size = packet_size; mod->hdr.src_port = 0; mod->hdr.dest_port = 0; mod->hdr.token = 0; mod->meminfo.data_payload_addr_lsw = 0; mod->meminfo.data_payload_addr_msw = 0; mod->meminfo.mem_map_handle = 0; mod->meminfo.buffer_size = payload_size; if (preload_type == AVCS_LOAD_MODULES) mod->hdr.opcode = AVCS_CMD_LOAD_MODULES; else mod->hdr.opcode = AVCS_CMD_UNLOAD_MODULES; q6core_lcl.avcs_module_resp_received = 0; ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *)mod); if (ret < 0) { pr_err("%s: modules load/unload failed ret = %d\n", __func__, ret); goto done; } ret = wait_event_timeout(q6core_lcl.avcs_module_load_unload_wait, (q6core_lcl.avcs_module_resp_received == 1), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s wait event timeout for avcs load/unload module\n", __func__); ret = -ETIMEDOUT; goto done; } if (q6core_lcl.adsp_status < 0) { pr_err("%s: modules load/unload failed %d\n", __func__, q6core_lcl.adsp_status); ret = q6core_lcl.adsp_status; goto done; } else { if (mod->hdr.opcode == AVCS_CMD_LOAD_MODULES) memcpy(payload, rsp_payload, payload_size); } done: kfree(mod); kfree(rsp_payload); mutex_unlock(&(q6core_lcl.cmd_lock)); return ret; } EXPORT_SYMBOL(q6core_avcs_load_unload_modules); int32_t q6core_load_unload_topo_modules(uint32_t topo_id, bool preload_type) { Loading Loading @@ -1871,7 +2004,6 @@ static int q6core_probe(struct platform_device *pdev) if (rc < 0) goto err; q6core_lcl.avs_state = avs_state; rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); if (rc) { dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", Loading Loading @@ -1926,6 +2058,7 @@ int __init core_init(void) init_waitqueue_head(&q6core_lcl.avcs_fwk_ver_req_wait); init_waitqueue_head(&q6core_lcl.mdf_map_resp_wait); init_waitqueue_head(&q6core_lcl.lpass_npa_rsc_wait); init_waitqueue_head(&q6core_lcl.avcs_module_load_unload_wait); q6core_lcl.cmd_resp_received_flag = FLAG_NONE; mutex_init(&q6core_lcl.cmd_lock); mutex_init(&q6core_lcl.ver_lock); Loading
include/dsp/apr_audio-v2.h +10 −0 Original line number Diff line number Diff line Loading @@ -4143,6 +4143,16 @@ struct afe_id_aptx_adaptive_enc_init #define AFE_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AFE_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 /* Macros for dynamic loading of modules by AVCS */ #define AVS_MODULE_ID_PACKETIZER_COP 0x0001322A #define AVS_MODULE_ID_PACKETIZER_COP_V1 0x000132E8 #define AVS_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AVS_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 /* * Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module. * This parameter cannot be set runtime. Loading
include/dsp/q6core.h +121 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #define AVCS_CMD_ADSP_EVENT_GET_STATE 0x0001290C #define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D #define AVCS_API_VERSION_V4 4 #define AVCS_API_VERSION_V5 5 #define APRV2_IDS_SERVICE_ID_ADSP_CORE_V (0x3) bool q6core_is_adsp_ready(void); Loading Loading @@ -198,6 +199,126 @@ struct avcs_cmd_load_unload_topo_modules { uint32_t topology_id; } __packed; #define AVCS_LOAD_MODULES 1 #define AVCS_UNLOAD_MODULES 0 #define AVCS_CMD_LOAD_MODULES 0x00012989 #define AVCS_CMD_UNLOAD_MODULES 0x0001298A #define AVCS_CMD_RSP_LOAD_MODULES 0x0001298B /* * Module is generic, such as a preprocessor, * postprocessor, or volume control * module. */ #define AMDB_MODULE_TYPE_GENERIC 0 /** Module is a decoder. */ #define AMDB_MODULE_TYPE_DECODER 1 /** Module is an encoder. */ #define AMDB_MODULE_TYPE_ENCODER 2 /** Module is a converter. */ #define AMDB_MODULE_TYPE_CONVERTER 3 /** Module is a packetizer. */ #define AMDB_MODULE_TYPE_PACKETIZER 4 /** Module is a depacketizer. */ #define AMDB_MODULE_TYPE_DEPACKETIZER 5 struct avcs_load_unload_modules_sec_payload { uint32_t module_type; /* * < Type of module. * @values * - #AMDB_MODULE_TYPE_GENERIC * - #AMDB_MODULE_TYPE_DECODER * - #AMDB_MODULE_TYPE_ENCODER * - #AMDB_MODULE_TYPE_CONVERTER * - #AMDB_MODULE_TYPE_PACKETIZER * - #AMDB_MODULE_TYPE_DEPACKETIZER */ uint32_t id1; /* * < One of the following types of IDs: * - Format ID for the encoder, decoder, and packetizer module types * - Module ID for the generic module type * - Source format ID for the converter module type */ uint32_t id2; /* * < Sink format ID for the converter module type. * Zero for other module types */ uint32_t handle_lsw; /* < LSW of the Handle to the module loaded */ uint32_t handle_msw; /* < MSW of the Handle to the module loaded. */ } __packed; struct avcs_load_unload_modules_payload { uint32_t num_modules; /**< Number of modules being registered */ struct avcs_load_unload_modules_sec_payload load_unload_info[0]; /* * < Load/unload information for num_modules. * It will be of type avcs_load_unload_info_t[num_modules] */ } __packed; struct avcs_load_unload_modules_meminfo { uint32_t data_payload_addr_lsw; /**< Lower 32 bits of the 64-bit data payload address. */ uint32_t data_payload_addr_msw; /**< Upper 32 bits of the 64-bit data payload address. */ uint32_t mem_map_handle; /* * < Unique identifier for an address. The aDSP returns this memory map * handle through the #AVCS_CMD_SHARED_MEM_MAP_REGIONS command. * @values @vertspace{-2} * - NULL -- Parameter data payloads are within the message payload * (in-band). * - Non-NULL -- Parameter data payloads begin at the address specified * in the data_payload_addr_lsw and data_payload_addr_msw fields * (out-of-band). * The client can choose in-band or out-of-band */ uint32_t buffer_size; /* * < Actual size (in bytes) of the valid data * in the data payload address. */ } __packed; struct avcs_cmd_dynamic_modules { struct apr_hdr hdr; struct avcs_load_unload_modules_meminfo meminfo; struct avcs_load_unload_modules_payload payload; } __packed; int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload *payload, uint32_t preload_type); /* This command allows a remote client(HLOS) creates a client to LPASS NPA * resource node. Currently, this command supports only the NPA Sleep resource * "/island/core/drivers" node ID. Loading