Merge "ASoC: msm: qdsp6v2: enable DMA channel control"
This commit is contained in:
commit
5c49e73d6d
3 changed files with 552 additions and 1 deletions
|
@ -3512,6 +3512,263 @@ struct afe_param_id_set_topology_cfg {
|
|||
u32 topology_id;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This command is used by client to request the LPASS resources.
|
||||
* Currently this command supports only LPAIF DMA resources.
|
||||
* Allocated resources will be in control of remote client until
|
||||
* they get released.
|
||||
*
|
||||
* If all the requested resources are available then response status in
|
||||
* AFE_CMDRSP_REQUEST_LPASS_RESOURCES payload will
|
||||
* be updated with ADSP_EOK, otherwise it will be ADSP_EFAILED.
|
||||
*
|
||||
* This command is variable payload size command, and size depends
|
||||
* on the type of resource requested.
|
||||
*
|
||||
* For example, if client requests AFE_LPAIF_DMA_RESOURCE_ID
|
||||
* resources, afe_cmd_request_lpass_resources structure will
|
||||
* be followed with the afe_cmd_request_lpass_dma_resources
|
||||
* structure.
|
||||
*
|
||||
* AFE_CMDRSP_REQUEST_LPASS_RESOURCES is the response for
|
||||
* this command, which returns the allocated resources.
|
||||
*
|
||||
* @apr_hdr_fields
|
||||
* Opcode -- AFE_CMD_REQUEST_LPASS_RESOURCES
|
||||
*
|
||||
* @return
|
||||
* #AFE_CMDRSP_REQUEST_LPASS_RESOURCES
|
||||
*/
|
||||
#define AFE_CMD_REQUEST_LPASS_RESOURCES 0x00010109
|
||||
|
||||
/* Macro for requesting LPAIF DMA resources */
|
||||
#define AFE_LPAIF_DMA_RESOURCE_ID 0x00000001
|
||||
|
||||
struct afe_cmd_request_lpass_resources {
|
||||
/*
|
||||
* LPASS Resource ID
|
||||
* @values:
|
||||
* - AFE_LPAIF_DMA_RESOURCE_ID
|
||||
*/
|
||||
u32 resource_id;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* AFE_CMD_REQUEST_LPASS_RESOURCES uses this structure when
|
||||
* client is requesting LPAIF DMA resources.
|
||||
*
|
||||
* Number of read DMA channels and write DMA channels varies from chipset to
|
||||
* chipset. HLOS needs to make sure that when it requests LPASS DMA
|
||||
* resources, it should not impact the concurrencies which
|
||||
* are mandatory for a given chipset.
|
||||
*/
|
||||
|
||||
/* Macro for AFE LPAIF default DMA data type */
|
||||
#define AFE_LPAIF_DEFAULT_DMA_TYPE 0x0
|
||||
|
||||
struct afe_cmd_request_lpass_dma_resources {
|
||||
/*
|
||||
* LPASS DMA Type
|
||||
* @values:
|
||||
* - AFE_LPAIF_DEFAULT_DMA_TYPE
|
||||
*/
|
||||
u8 dma_type;
|
||||
/*
|
||||
* Number of read DMA channels required
|
||||
* @values: >=0
|
||||
* - 0 indicates channels are not requested
|
||||
*/
|
||||
u8 num_read_dma_channels;
|
||||
/*
|
||||
* Number of write DMA channels required
|
||||
* @values: >=0
|
||||
* - 0 indicates channels are not requested
|
||||
*/
|
||||
u8 num_write_dma_channels;
|
||||
/*
|
||||
* Reserved field for 4 byte alignment
|
||||
* @values: 0
|
||||
*/
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct afe_request_lpass_dma_resources_command {
|
||||
struct apr_hdr hdr;
|
||||
struct afe_cmd_request_lpass_resources resources;
|
||||
struct afe_cmd_request_lpass_dma_resources dma_resources;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This is the response for the command AFE_CMD_REQUEST_LPASS_RESOURCES.
|
||||
* Payload of this command is variable.
|
||||
*
|
||||
* Resources allocated successfully or not, are determined by the "status"
|
||||
* in the payload. If status is ADSP_EOK, then resources are
|
||||
* allocated successfully and allocated resource information
|
||||
* follows.
|
||||
*
|
||||
* For example, if the response resource id is AFE_LPAIF_DMA_RESOURCE_ID,
|
||||
* afe_cmdrsp_request_lpass_dma_resources structure will
|
||||
* follow after afe_cmdrsp_request_lpass_resources.
|
||||
*
|
||||
* If status is ADSP_EFAILED, this indicates requested resources
|
||||
* are not allocated successfully. In this case the payload following
|
||||
* this structure is invalid.
|
||||
* @apr_hdr_fields
|
||||
* Opcode -- AFE_CMDRSP_REQUEST_LPASS_RESOURCES
|
||||
*/
|
||||
#define AFE_CMDRSP_REQUEST_LPASS_RESOURCES 0x0001010A
|
||||
|
||||
struct afe_cmdrsp_request_lpass_resources {
|
||||
/*
|
||||
* ADSP_EOK if all requested resources are allocated.
|
||||
* ADSP_EFAILED if resource allocation is failed.
|
||||
*/
|
||||
u32 status;
|
||||
/*
|
||||
* Returned LPASS DMA resource ID
|
||||
* @values:
|
||||
* - AFE_LPAIF_DMA_RESOURCE_ID
|
||||
*/
|
||||
u32 resource_id;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This command will be sent as a payload for
|
||||
* AFE_CMDRSP_REQUEST_LPASS_RESOURCES, when the LPAIF DMA resources
|
||||
* were requested. Payload of this command is variable, which
|
||||
* follows after the afe_cmdrsp_request_lpass_dma_resources structure.
|
||||
* The size in bytes following this structure is sum of
|
||||
* num_read_dma_channels and num_write_dma_channels.
|
||||
*
|
||||
* If the resource allocation is successful, then the payload contains
|
||||
* the valid DMA channel indices.
|
||||
*
|
||||
* For example, if number of requested DMA read channels is 2, and they
|
||||
* are successfully allocated, the variable payload contains
|
||||
* valid DMA channel index values in first two bytes array.
|
||||
*
|
||||
* In the failure case this payload can be ignored, and all the values will be
|
||||
* initialized with zeros.
|
||||
*
|
||||
* An example payload of the command response is below:
|
||||
* <struct afe_cmdrsp_request_lpass_resources>
|
||||
* <struct afe_cmdrsp_request_lpass_dma_resources>
|
||||
* read DMA index value for each byte.
|
||||
* write DMA index value for each byte.
|
||||
* padded zeros, if sum of num_read_dma_channels and num_write_dma_channels
|
||||
* are not multiples of 4.
|
||||
*/
|
||||
|
||||
struct afe_cmdrsp_request_lpass_dma_resources {
|
||||
/*
|
||||
* LPASS DMA Type
|
||||
* @values:
|
||||
* - AFE_LPAIF_DEFAULT_DMA_TYPE
|
||||
*/
|
||||
u8 dma_type;
|
||||
/*
|
||||
* Returned number of read DMA channels allocated
|
||||
* @values: >=0
|
||||
*/
|
||||
u8 num_read_dma_channels;
|
||||
/*
|
||||
* Returned number of write DMA channels allocated
|
||||
* @values: >=0
|
||||
*/
|
||||
u8 num_write_dma_channels;
|
||||
/*
|
||||
* Reserved field for 4 byte alignment
|
||||
* @values: 0
|
||||
*/
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This command is for releasing resources which are allocated as
|
||||
* part of AFE_CMD_REQUEST_LPASS_RESOURCES.
|
||||
*
|
||||
* Payload of this command is variable, which follows
|
||||
* after the afe_cmd_release_lpass_resources structure.
|
||||
*
|
||||
* If release resource is AFE_LPAIF_DMA_RESOURCE_ID
|
||||
* afe_cmd_release_lpass_dma_resources structure will be
|
||||
* followed after afe_cmd_release_lpass_resources.
|
||||
*
|
||||
*
|
||||
* @apr_hdr_fields
|
||||
* Opcode -- AFE_CMD_RELEASE_LPASS_RESOURCES
|
||||
|
||||
* @return
|
||||
* #APRv2 IBASIC RSP Result
|
||||
*/
|
||||
#define AFE_CMD_RELEASE_LPASS_RESOURCES 0x0001010B
|
||||
|
||||
struct afe_cmd_release_lpass_resources {
|
||||
/*
|
||||
* LPASS DMA resource ID
|
||||
* @values:
|
||||
* - AFE_LPAIF_DMA_RESOURCE_ID
|
||||
*/
|
||||
u32 resource_id;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This payload to be appended as part of AFE_CMD_RELEASE_LPASS_RESOURCES
|
||||
* when resource id AFE_LPAIF_DMA_RESOURCE_ID is used.
|
||||
*
|
||||
* Payload of this command is variable, which will be followed after the
|
||||
* afe_cmd_release_lpass_dma_resources structure.
|
||||
* The variable payload's size in bytes is sum of
|
||||
* num_read_dma_channels and num_write_dma_channels.
|
||||
* Variable payload data contains the valid DMA channel indices which are
|
||||
* allocated as part of AFE_CMD_REQUEST_LPASS_RESOURCES.
|
||||
*
|
||||
* For example, if number of DMA read channels released are 2,
|
||||
* the variable payload contains valid DMA channel
|
||||
* index values in first two bytes of variable payload.
|
||||
* Client needs to fill the same DMA channel indices were returned
|
||||
* as part of AFE_CMD_RELEASE_LPASS_RESOURCES, otherwise
|
||||
* ADSP will return the error.
|
||||
*
|
||||
* An example payload of the release command is below:
|
||||
* <struct afe_cmd_release_lpass_resources>
|
||||
* <struct afe_cmd_release_lpass_dma_resources>
|
||||
* read DMA index value for each byte.
|
||||
* write DMA index value for each byte.
|
||||
*/
|
||||
|
||||
struct afe_cmd_release_lpass_dma_resources {
|
||||
/*
|
||||
* LPASS DMA Type
|
||||
* @values:
|
||||
* - AFE_LPAIF_DEFAULT_DMA_TYPE
|
||||
*/
|
||||
u8 dma_type;
|
||||
/*
|
||||
* Number of read DMA channels to be released
|
||||
* @values: >=0
|
||||
* - 0 indicates channels are not released
|
||||
*/
|
||||
u8 num_read_dma_channels;
|
||||
/*
|
||||
* Number of write DMA channels to be released
|
||||
* @values: >=0
|
||||
* - 0 indicates channels are not released
|
||||
*/
|
||||
u8 num_write_dma_channels;
|
||||
/*
|
||||
* Reserved field for 4 byte alignment
|
||||
* @values: 0
|
||||
*/
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
struct afe_release_lpass_dma_resources_command {
|
||||
struct apr_hdr hdr;
|
||||
struct afe_cmd_release_lpass_resources resources;
|
||||
struct afe_cmd_release_lpass_dma_resources dma_resources;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Generic encoder module ID.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -42,6 +42,9 @@
|
|||
#define AFE_CLK_VERSION_V1 1
|
||||
#define AFE_CLK_VERSION_V2 2
|
||||
|
||||
#define AFE_MAX_RDDMA 10
|
||||
#define AFE_MAX_WRDMA 10
|
||||
|
||||
typedef int (*routing_cb)(int port);
|
||||
|
||||
enum {
|
||||
|
@ -450,4 +453,9 @@ void afe_set_routing_callback(routing_cb);
|
|||
int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
|
||||
u16 port);
|
||||
int afe_get_svc_version(uint32_t service_id);
|
||||
int afe_request_dma_resources(uint8_t dma_type, uint8_t num_read_dma_channels,
|
||||
uint8_t num_write_dma_channels);
|
||||
int afe_get_dma_idx(bool **ret_rddma_idx,
|
||||
bool **ret_wrdma_idx);
|
||||
int afe_release_all_dma_resources(void);
|
||||
#endif /* __Q6AFE_V2_H__ */
|
||||
|
|
|
@ -124,6 +124,10 @@ struct afe_ctl {
|
|||
int set_custom_topology;
|
||||
int dev_acdb_id[AFE_MAX_PORTS];
|
||||
routing_cb rt_cb;
|
||||
int num_alloced_rddma;
|
||||
bool alloced_rddma[AFE_MAX_RDDMA];
|
||||
int num_alloced_wrdma;
|
||||
bool alloced_wrdma[AFE_MAX_WRDMA];
|
||||
};
|
||||
|
||||
static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
|
||||
|
@ -385,6 +389,99 @@ static int32_t sp_make_afe_callback(uint32_t opcode, uint32_t *payload,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t afe_lpass_resources_callback(struct apr_client_data *data)
|
||||
{
|
||||
uint8_t *payload = data->payload;
|
||||
struct afe_cmdrsp_request_lpass_resources *resources =
|
||||
(struct afe_cmdrsp_request_lpass_resources *) payload;
|
||||
struct afe_cmdrsp_request_lpass_dma_resources *dma_resources = NULL;
|
||||
uint8_t *dma_channels_id_payload = NULL;
|
||||
|
||||
if (!payload || (data->token >= AFE_MAX_PORTS)) {
|
||||
pr_err("%s: Error: size %d payload %pK token %d\n",
|
||||
__func__, data->payload_size,
|
||||
payload, data->token);
|
||||
atomic_set(&this_afe.status, ADSP_EBADPARAM);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (resources->status != 0) {
|
||||
pr_debug("%s: Error: Requesting LPASS resources ret %d\n",
|
||||
__func__, resources->status);
|
||||
atomic_set(&this_afe.status, ADSP_EBADPARAM);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (resources->resource_id == AFE_LPAIF_DMA_RESOURCE_ID) {
|
||||
int i;
|
||||
|
||||
payload += sizeof(
|
||||
struct afe_cmdrsp_request_lpass_resources);
|
||||
dma_resources = (struct
|
||||
afe_cmdrsp_request_lpass_dma_resources *)
|
||||
payload;
|
||||
|
||||
pr_debug("%s: DMA Type allocated = %d\n",
|
||||
__func__,
|
||||
dma_resources->dma_type);
|
||||
|
||||
if (dma_resources->num_read_dma_channels > AFE_MAX_RDDMA) {
|
||||
pr_err("%s: Allocated Read DMA %d exceeds max %d\n",
|
||||
__func__,
|
||||
dma_resources->num_read_dma_channels,
|
||||
AFE_MAX_RDDMA);
|
||||
dma_resources->num_read_dma_channels = AFE_MAX_RDDMA;
|
||||
}
|
||||
|
||||
if (dma_resources->num_write_dma_channels > AFE_MAX_WRDMA) {
|
||||
pr_err("%s: Allocated Write DMA %d exceeds max %d\n",
|
||||
__func__,
|
||||
dma_resources->num_write_dma_channels,
|
||||
AFE_MAX_WRDMA);
|
||||
dma_resources->num_write_dma_channels = AFE_MAX_WRDMA;
|
||||
}
|
||||
|
||||
this_afe.num_alloced_rddma =
|
||||
dma_resources->num_read_dma_channels;
|
||||
this_afe.num_alloced_wrdma =
|
||||
dma_resources->num_write_dma_channels;
|
||||
|
||||
pr_debug("%s: Number of allocated Read DMA channels= %d\n",
|
||||
__func__,
|
||||
dma_resources->num_read_dma_channels);
|
||||
pr_debug("%s: Number of allocated Write DMA channels= %d\n",
|
||||
__func__,
|
||||
dma_resources->num_write_dma_channels);
|
||||
|
||||
payload += sizeof(
|
||||
struct afe_cmdrsp_request_lpass_dma_resources);
|
||||
dma_channels_id_payload = payload;
|
||||
|
||||
for (i = 0; i < this_afe.num_alloced_rddma; i++) {
|
||||
pr_debug("%s: Read DMA Index %d allocated\n",
|
||||
__func__, *dma_channels_id_payload);
|
||||
this_afe.alloced_rddma
|
||||
[*dma_channels_id_payload] = 1;
|
||||
dma_channels_id_payload++;
|
||||
}
|
||||
|
||||
for (i = 0; i < this_afe.num_alloced_wrdma; i++) {
|
||||
pr_debug("%s: Write DMA Index %d allocated\n",
|
||||
__func__, *dma_channels_id_payload);
|
||||
this_afe.alloced_wrdma
|
||||
[*dma_channels_id_payload] = 1;
|
||||
dma_channels_id_payload++;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: Error: Unknown resource ID %d",
|
||||
__func__, resources->resource_id);
|
||||
atomic_set(&this_afe.status, ADSP_EBADPARAM);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t afe_callback(struct apr_client_data *data, void *priv)
|
||||
{
|
||||
if (!data) {
|
||||
|
@ -472,6 +569,15 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
|
|||
return -EINVAL;
|
||||
}
|
||||
wake_up(&this_afe.wait[data->token]);
|
||||
} else if (data->opcode == AFE_CMDRSP_REQUEST_LPASS_RESOURCES) {
|
||||
uint32_t ret = 0;
|
||||
|
||||
ret = afe_lpass_resources_callback(data);
|
||||
atomic_set(&this_afe.state, 0);
|
||||
wake_up(&this_afe.wait[data->token]);
|
||||
if (!ret) {
|
||||
return ret;
|
||||
}
|
||||
} else if (data->payload_size) {
|
||||
uint32_t *payload;
|
||||
uint16_t port_id = 0;
|
||||
|
@ -502,6 +608,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
|
|||
case AFE_PORTS_CMD_DTMF_CTL:
|
||||
case AFE_SVC_CMD_SET_PARAM:
|
||||
case AFE_SVC_CMD_SET_PARAM_V2:
|
||||
case AFE_CMD_REQUEST_LPASS_RESOURCES:
|
||||
atomic_set(&this_afe.state, 0);
|
||||
wake_up(&this_afe.wait[data->token]);
|
||||
break;
|
||||
|
@ -541,6 +648,18 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
|
|||
atomic_set(&this_afe.state, payload[1]);
|
||||
wake_up(&this_afe.wait[data->token]);
|
||||
break;
|
||||
case AFE_CMD_RELEASE_LPASS_RESOURCES:
|
||||
memset(&this_afe.alloced_rddma[0],
|
||||
0,
|
||||
AFE_MAX_RDDMA);
|
||||
memset(&this_afe.alloced_wrdma[0],
|
||||
0,
|
||||
AFE_MAX_WRDMA);
|
||||
this_afe.num_alloced_rddma = 0;
|
||||
this_afe.num_alloced_wrdma = 0;
|
||||
atomic_set(&this_afe.state, 0);
|
||||
wake_up(&this_afe.wait[data->token]);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Unknown cmd 0x%x\n", __func__,
|
||||
payload[0]);
|
||||
|
@ -6598,6 +6717,173 @@ done:
|
|||
return result;
|
||||
}
|
||||
|
||||
int afe_request_dma_resources(uint8_t dma_type, uint8_t num_read_dma_channels,
|
||||
uint8_t num_write_dma_channels)
|
||||
{
|
||||
int result = 0;
|
||||
struct afe_request_lpass_dma_resources_command config;
|
||||
|
||||
pr_debug("%s:\n", __func__);
|
||||
|
||||
if (dma_type != AFE_LPAIF_DEFAULT_DMA_TYPE) {
|
||||
pr_err("%s: DMA type %d is invalid\n",
|
||||
__func__,
|
||||
dma_type);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((num_read_dma_channels == 0) &&
|
||||
(num_write_dma_channels == 0)) {
|
||||
pr_err("%s: DMA channels to allocate are 0\n",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (num_read_dma_channels > AFE_MAX_RDDMA) {
|
||||
pr_err("%s: Read DMA channels %d to allocate are > %d\n",
|
||||
__func__,
|
||||
num_read_dma_channels,
|
||||
AFE_MAX_RDDMA);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (num_write_dma_channels > AFE_MAX_WRDMA) {
|
||||
pr_err("%s: Write DMA channels %d to allocate are > %d\n",
|
||||
__func__,
|
||||
num_write_dma_channels,
|
||||
AFE_MAX_WRDMA);
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = afe_q6_interface_prepare();
|
||||
if (result != 0) {
|
||||
pr_err("%s: Q6 interface prepare failed %d\n",
|
||||
__func__, result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
||||
APR_HDR_LEN(APR_HDR_SIZE),
|
||||
APR_PKT_VER);
|
||||
config.hdr.pkt_size = sizeof(config);
|
||||
config.hdr.src_port = 0;
|
||||
config.hdr.dest_port = 0;
|
||||
config.hdr.token = IDX_GLOBAL_CFG;
|
||||
config.hdr.opcode = AFE_CMD_REQUEST_LPASS_RESOURCES;
|
||||
config.resources.resource_id = AFE_LPAIF_DMA_RESOURCE_ID;
|
||||
/* Only AFE_LPAIF_DEFAULT_DMA_TYPE dma type is supported */
|
||||
config.dma_resources.dma_type = dma_type;
|
||||
config.dma_resources.num_read_dma_channels = num_read_dma_channels;
|
||||
config.dma_resources.num_write_dma_channels = num_write_dma_channels;
|
||||
|
||||
result = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
|
||||
if (result)
|
||||
pr_err("%s: AFE_CMD_REQUEST_LPASS_RESOURCES failed %d\n",
|
||||
__func__, result);
|
||||
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL(afe_request_dma_resources);
|
||||
|
||||
int afe_get_dma_idx(bool **ret_rddma_idx,
|
||||
bool **ret_wrdma_idx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!ret_rddma_idx || !ret_wrdma_idx) {
|
||||
pr_err("%s: invalid return pointers.", __func__);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*ret_rddma_idx = &this_afe.alloced_rddma[0];
|
||||
*ret_wrdma_idx = &this_afe.alloced_wrdma[0];
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(afe_get_dma_idx);
|
||||
|
||||
int afe_release_all_dma_resources(void)
|
||||
{
|
||||
int result = 0;
|
||||
int i, total_size;
|
||||
struct afe_release_lpass_dma_resources_command *config;
|
||||
uint8_t *payload;
|
||||
|
||||
pr_debug("%s:\n", __func__);
|
||||
|
||||
if ((this_afe.num_alloced_rddma == 0) &&
|
||||
(this_afe.num_alloced_wrdma == 0)) {
|
||||
pr_err("%s: DMA channels to release is 0",
|
||||
__func__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = afe_q6_interface_prepare();
|
||||
if (result != 0) {
|
||||
pr_err("%s: Q6 interface prepare failed %d\n",
|
||||
__func__, result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
total_size = sizeof(struct afe_release_lpass_dma_resources_command) +
|
||||
sizeof(uint8_t) *
|
||||
(this_afe.num_alloced_rddma + this_afe.num_alloced_wrdma);
|
||||
|
||||
config = kzalloc(total_size, GFP_KERNEL);
|
||||
if (!config) {
|
||||
result = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(config, 0, total_size);
|
||||
payload = (uint8_t *) config +
|
||||
sizeof(struct afe_release_lpass_dma_resources_command);
|
||||
|
||||
config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
||||
APR_HDR_LEN(APR_HDR_SIZE),
|
||||
APR_PKT_VER);
|
||||
config->hdr.pkt_size = total_size;
|
||||
config->hdr.src_port = 0;
|
||||
config->hdr.dest_port = 0;
|
||||
config->hdr.token = IDX_GLOBAL_CFG;
|
||||
config->hdr.opcode = AFE_CMD_RELEASE_LPASS_RESOURCES;
|
||||
config->resources.resource_id = AFE_LPAIF_DMA_RESOURCE_ID;
|
||||
/* Only AFE_LPAIF_DEFAULT_DMA_TYPE dma type is supported */
|
||||
config->dma_resources.dma_type = AFE_LPAIF_DEFAULT_DMA_TYPE;
|
||||
config->dma_resources.num_read_dma_channels =
|
||||
this_afe.num_alloced_rddma;
|
||||
config->dma_resources.num_write_dma_channels =
|
||||
this_afe.num_alloced_wrdma;
|
||||
|
||||
for (i = 0; i < AFE_MAX_RDDMA; i++) {
|
||||
if (this_afe.alloced_rddma[i]) {
|
||||
*payload = i;
|
||||
payload++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < AFE_MAX_WRDMA; i++) {
|
||||
if (this_afe.alloced_wrdma[i]) {
|
||||
*payload = i;
|
||||
payload++;
|
||||
}
|
||||
}
|
||||
|
||||
result = afe_apr_send_pkt(config, &this_afe.wait[IDX_GLOBAL_CFG]);
|
||||
if (result)
|
||||
pr_err("%s: AFE_CMD_RELEASE_LPASS_RESOURCES failed %d\n",
|
||||
__func__, result);
|
||||
|
||||
kfree(config);
|
||||
done:
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL(afe_release_all_dma_resources);
|
||||
|
||||
static int __init afe_init(void)
|
||||
{
|
||||
int i = 0, ret;
|
||||
|
|
Loading…
Add table
Reference in a new issue