blob: b5444b134732e37bdcfdcdf32abfbfde80198d5f [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*/
#include <dsp/q6common.h>
struct q6common_ctl {
bool instance_id_supported;
};
static struct q6common_ctl common;
/**
* q6common_update_instance_id_support
*
* Update instance ID support flag to true/false
*
* @supported: enable/disable for instance ID support
*/
void q6common_update_instance_id_support(bool supported)
{
common.instance_id_supported = supported;
}
EXPORT_SYMBOL(q6common_update_instance_id_support);
/**
* q6common_is_instance_id_supported
*
* Returns true/false for instance ID support
*/
bool q6common_is_instance_id_supported(void)
{
return common.instance_id_supported;
}
EXPORT_SYMBOL(q6common_is_instance_id_supported);
/**
* q6common_pack_pp_params
*
* Populate params header based on instance ID support and pack
* it with payload.
* Instance ID support -
* yes - param_hdr_v3 + payload
* no - param_hdr_v1 + payload
*
* @dest: destination data pointer to be packed into
* @v3_hdr: param header v3
* @param_data: param payload
* @total_size: total size of packed data (hdr + payload)
*
* Returns 0 on success or error on failure
*/
int q6common_pack_pp_params(u8 *dest, struct param_hdr_v3 *v3_hdr,
u8 *param_data, u32 *total_size)
{
struct param_hdr_v1 *v1_hdr = NULL;
u32 packed_size = 0;
u32 param_size = 0;
bool iid_supported = q6common_is_instance_id_supported();
if (dest == NULL) {
pr_err("%s: Received NULL pointer for destination\n", __func__);
return -EINVAL;
} else if (v3_hdr == NULL) {
pr_err("%s: Received NULL pointer for header\n", __func__);
return -EINVAL;
} else if (total_size == NULL) {
pr_err("%s: Received NULL pointer for total size\n", __func__);
return -EINVAL;
}
param_size = v3_hdr->param_size;
packed_size = iid_supported ? sizeof(struct param_hdr_v3) :
sizeof(struct param_hdr_v1);
if (iid_supported) {
memcpy(dest, v3_hdr, packed_size);
} else {
v1_hdr = (struct param_hdr_v1 *) dest;
v1_hdr->module_id = v3_hdr->module_id;
v1_hdr->param_id = v3_hdr->param_id;
if (param_size > U16_MAX) {
pr_err("%s: Invalid param size for V1 %d\n", __func__,
param_size);
return -EINVAL;
}
v1_hdr->param_size = param_size;
v1_hdr->reserved = 0;
}
/*
* Make param_data optional for cases when there is no data
* present as in some set cases and all get cases.
*/
if (param_data != NULL) {
memcpy(dest + packed_size, param_data, param_size);
packed_size += param_size;
}
*total_size = packed_size;
return 0;
}
EXPORT_SYMBOL(q6common_pack_pp_params);
/**
* q6common_pack_pp_params_v2
*
* Populate params header based on instance ID support and pack
* it with payload.
* Instance ID support -
* yes - param_hdr_v3 + payload
* no - param_hdr_v1 + payload
*
* @dest: destination data pointer to be packed into
* @v3_hdr: param header v3
* @param_data: param payload
* @total_size: total size of packed data (hdr + payload)
* @iid_supported: Instance ID supported or not
*
* Returns 0 on success or error on failure
*/
int q6common_pack_pp_params_v2(u8 *dest, struct param_hdr_v3 *v3_hdr,
u8 *param_data, u32 *total_size,
bool iid_supported)
{
struct param_hdr_v1 *v1_hdr = NULL;
u32 packed_size = 0;
u32 param_size = 0;
if (dest == NULL) {
pr_err("%s: Received NULL pointer for destination\n", __func__);
return -EINVAL;
} else if (v3_hdr == NULL) {
pr_err("%s: Received NULL pointer for header\n", __func__);
return -EINVAL;
} else if (total_size == NULL) {
pr_err("%s: Received NULL pointer for total size\n", __func__);
return -EINVAL;
}
param_size = v3_hdr->param_size;
packed_size = iid_supported ? sizeof(struct param_hdr_v3) :
sizeof(struct param_hdr_v1);
if (iid_supported) {
memcpy(dest, v3_hdr, packed_size);
} else {
v1_hdr = (struct param_hdr_v1 *) dest;
v1_hdr->module_id = v3_hdr->module_id;
v1_hdr->param_id = v3_hdr->param_id;
if (param_size > U16_MAX) {
pr_err("%s: Invalid param size for V1 %d\n", __func__,
param_size);
return -EINVAL;
}
v1_hdr->param_size = param_size;
v1_hdr->reserved = 0;
}
/*
* Make param_data optional for cases when there is no data
* present as in some set cases and all get cases.
*/
if (param_data != NULL) {
memcpy(dest + packed_size, param_data, param_size);
packed_size += param_size;
}
*total_size = packed_size;
return 0;
}
EXPORT_SYMBOL(q6common_pack_pp_params_v2);