ASoC: q6dspv2: Support for pan-scale and downmix set param

Add support for set params on ASM/ADM for MFC and
Volume modules. Make PSPD mitrix set param api generic.

Change-Id: I75a5b9e3fd2316b75be41439848f89190944bc36
Signed-off-by: Varun Balaraj <varunb@codeaurora.org>
This commit is contained in:
Varun Balaraj 2017-07-13 13:30:15 +05:30 committed by Gerrit - the friendly Code Review server
parent d9fbe4b921
commit 701ac49eb7
6 changed files with 368 additions and 12 deletions

View file

@ -625,6 +625,10 @@ struct audproc_softvolume_params {
*/
#define AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT 0x00010913
/* ID of the Coefficient parameter used by AUDPROC_MODULE_ID_CHMIXER to
*configure the channel mixer weighting coefficients.
*/
#define AUDPROC_CHMIXER_PARAM_ID_COEFF 0x00010342
struct audproc_mfc_output_media_fmt {
struct adm_cmd_set_pp_params_v5 params;
@ -3902,6 +3906,14 @@ struct asm_softvolume_params {
u32 rampingcurve;
} __packed;
struct asm_stream_pan_ctrl_params {
uint16_t num_output_channels;
uint16_t num_input_channels;
uint16_t output_channel_map[8];
uint16_t input_channel_map[8];
uint16_t gain[64];
} __packed;
#define ASM_END_POINT_DEVICE_MATRIX 0
#define PCM_CHANNEL_NULL 0
@ -7802,6 +7814,48 @@ struct asm_volume_ctrl_lr_chan_gain {
/*< Linear gain in Q13 format for the right channel.*/
} __packed;
struct audproc_chmixer_param_coeff {
uint32_t index;
uint16_t num_output_channels;
uint16_t num_input_channels;
} __packed;
/* ID of the Multichannel Volume Control parameters used by
* AUDPROC_MODULE_ID_VOL_CTRL.
*/
#define AUDPROC_PARAM_ID_MULTICHANNEL_GAIN 0x00010713
/* Payload of the AUDPROC_PARAM_ID_MULTICHANNEL_GAIN channel type/gain
* pairs used by the Volume Control module.
* This structure immediately follows the
* audproc_volume_ctrl_multichannel_gain_t structure.
*/
struct audproc_volume_ctrl_channel_type_gain_pair {
uint8_t channel_type;
/* Channel type for which the gain setting is to be applied. */
uint8_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
uint32_t gain;
/* Gain value for this channel in Q28 format. */
} __packed;
/* Payload of the AUDPROC_PARAM_ID_MULTICHANNEL_MUTE parameters used by
* the Volume Control module.
*/
struct audproc_volume_ctrl_multichannel_gain {
uint32_t num_channels;
/* Number of channels for which mute configuration is provided. Any
* channels present in the data for which mute configuration is not
* provided are set to unmute.
*/
struct audproc_volume_ctrl_channel_type_gain_pair *gain_data;
/* Array of channel type/mute setting pairs. */
} __packed;
/* Structure for the mute configuration parameter for a
volume control module. */

View file

@ -138,9 +138,13 @@ int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx);
int adm_get_indexes_from_copp_id(int copp_id, int *port_idx, int *copp_idx);
int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
unsigned int session_id,
char *params, uint32_t params_length);
int adm_set_pspd_matrix_params(int port_id, int copp_idx,
unsigned int session_id,
char *params, uint32_t params_length);
int adm_set_downmix_params(int port_id, int copp_idx,
unsigned int session_id, char *params,
uint32_t params_length);
int adm_get_pp_topo_module_list(int port_id, int copp_idx, int32_t param_length,
char *params);

View file

@ -611,6 +611,14 @@ int q6asm_set_softvolume(struct audio_client *ac,
int q6asm_set_softvolume_v2(struct audio_client *ac,
struct asm_softvolume_params *param, int instance);
/* Set panning and MFC params */
int q6asm_set_mfc_panning_params(struct audio_client *ac,
struct asm_stream_pan_ctrl_params *pan_param);
/* Set vol gain pair */
int q6asm_set_vol_ctrl_gain_pair(struct audio_client *ac,
struct asm_stream_pan_ctrl_params *pan_param);
/* Send left-right channel gain */
int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain);

View file

@ -298,11 +298,11 @@ int msm_qti_pp_send_stereo_to_custom_stereo_cmd(int port_id, int copp_idx,
*update_params_value16++ = op_FR_ip_FR_weight;
avail_length = avail_length - (4 * sizeof(uint16_t));
if (params_length) {
rc = adm_set_stereo_to_custom_stereo(port_id,
copp_idx,
session_id,
params_value,
params_length);
rc = adm_set_pspd_matrix_params(port_id,
copp_idx,
session_id,
params_value,
params_length);
if (rc) {
pr_err("%s: send params failed rc=%d\n", __func__, rc);
kfree(params_value);

View file

@ -781,9 +781,9 @@ fail_cmd:
return ret;
}
int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
unsigned int session_id, char *params,
uint32_t params_length)
int adm_set_pspd_matrix_params(int port_id, int copp_idx,
unsigned int session_id, char *params,
uint32_t params_length)
{
struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
int sz, rc = 0, port_idx;

View file

@ -44,7 +44,7 @@
#define TRUE 0x01
#define FALSE 0x00
#define SESSION_MAX 8
#define ASM_MAX_CHANNELS 8
enum {
ASM_TOPOLOGY_CAL = 0,
ASM_CUSTOM_TOP_CAL,
@ -7419,6 +7419,296 @@ int q6asm_set_softvolume_v2(struct audio_client *ac,
return __q6asm_set_softvolume(ac, softvol_param, instance);
}
int q6asm_set_vol_ctrl_gain_pair(struct audio_client *ac,
struct asm_stream_pan_ctrl_params *pan_param)
{
int sz = 0;
int rc = 0;
int i = 0;
int32_t ch = 0;
struct apr_hdr hdr;
struct audproc_volume_ctrl_channel_type_gain_pair
gain_data[ASM_MAX_CHANNELS];
struct asm_stream_cmd_set_pp_params_v2 payload_params;
struct asm_stream_param_data_v2 data;
uint16_t *asm_params = NULL;
if (ac == NULL) {
pr_err("%s: ac is NULL\n", __func__);
rc = -EINVAL;
goto fail;
}
if (ac->apr == NULL) {
dev_err(ac->dev, "%s: ac apr handle NULL\n", __func__);
rc = -EINVAL;
goto fail;
}
sz = sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2) +
sizeof(uint32_t) +
(sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) *
ASM_MAX_CHANNELS);
asm_params = kzalloc(sz, GFP_KERNEL);
if (!asm_params) {
rc = -ENOMEM;
goto fail;
}
q6asm_add_hdr_async(ac, &hdr, sz, TRUE);
atomic_set(&ac->cmd_state_pp, -1);
hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr));
payload_params.data_payload_addr_lsw = 0;
payload_params.data_payload_addr_msw = 0;
payload_params.mem_map_handle = 0;
payload_params.data_payload_size =
sizeof(struct asm_stream_param_data_v2) +
sizeof(uint32_t) +
(sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) *
ASM_MAX_CHANNELS);
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)),
&payload_params,
sizeof(struct asm_stream_cmd_set_pp_params_v2));
data.module_id = AUDPROC_MODULE_ID_VOL_CTRL;
data.param_id = AUDPROC_PARAM_ID_MULTICHANNEL_GAIN;
data.param_size = sizeof(uint32_t) +
(sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) *
ASM_MAX_CHANNELS);
data.reserved = 0;
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2)),
&data, sizeof(struct asm_stream_param_data_v2));
ch = pan_param->num_output_channels;
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2)),
&ch,
sizeof(uint32_t));
memset(gain_data, 0,
ASM_MAX_CHANNELS *
sizeof(struct audproc_volume_ctrl_channel_type_gain_pair));
for (i = 0; i < pan_param->num_output_channels; i++) {
gain_data[i].channel_type =
pan_param->output_channel_map[i];
gain_data[i].gain = pan_param->gain[i];
}
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2) +
sizeof(uint32_t)),
gain_data,
ASM_MAX_CHANNELS *
sizeof(struct audproc_volume_ctrl_channel_type_gain_pair));
rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
if (rc < 0) {
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
__func__, data.param_id, rc);
goto done;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state_pp) >= 0), 5 * HZ);
if (!rc) {
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
data.param_id);
rc = -EINVAL;
goto done;
}
if (atomic_read(&ac->cmd_state_pp) > 0) {
pr_err("%s: DSP returned error[%d], set-params paramid[0x%x]\n",
__func__, atomic_read(&ac->cmd_state_pp),
data.param_id);
rc = -EINVAL;
goto done;
}
rc = 0;
done:
kfree(asm_params);
fail:
return rc;
}
int q6asm_set_mfc_panning_params(struct audio_client *ac,
struct asm_stream_pan_ctrl_params *pan_param)
{
int sz, rc, i;
struct audproc_mfc_output_media_fmt mfc_cfg;
struct apr_hdr hdr;
struct asm_stream_cmd_set_pp_params_v2 payload_params;
struct asm_stream_param_data_v2 data;
struct audproc_chmixer_param_coeff pan_cfg;
uint16_t variable_payload = 0;
uint16_t *asm_params = NULL;
sz = rc = i = 0;
if (ac == NULL) {
pr_err("%s: ac handle NULL\n", __func__);
rc = -EINVAL;
goto fail_cmd1;
}
if (ac->apr == NULL) {
pr_err("%s: ac apr handle NULL\n", __func__);
rc = -EINVAL;
goto fail_cmd1;
}
sz = sizeof(struct audproc_mfc_output_media_fmt);
q6asm_add_hdr_async(ac, &mfc_cfg.params.hdr, sz, TRUE);
atomic_set(&ac->cmd_state_pp, -1);
mfc_cfg.params.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
mfc_cfg.params.payload_addr_lsw = 0;
mfc_cfg.params.payload_addr_msw = 0;
mfc_cfg.params.mem_map_handle = 0;
mfc_cfg.params.payload_size = sizeof(mfc_cfg) - sizeof(mfc_cfg.params);
mfc_cfg.data.module_id = AUDPROC_MODULE_ID_MFC;
mfc_cfg.data.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
mfc_cfg.data.param_size = mfc_cfg.params.payload_size -
sizeof(mfc_cfg.data);
mfc_cfg.data.reserved = 0;
mfc_cfg.sampling_rate = 0;
mfc_cfg.bits_per_sample = 0;
mfc_cfg.num_channels = pan_param->num_output_channels;
for (i = 0; i < mfc_cfg.num_channels; i++)
mfc_cfg.channel_type[i] = pan_param->output_channel_map[i];
rc = apr_send_pkt(ac->apr, (uint32_t *) &mfc_cfg);
if (rc < 0) {
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
__func__, mfc_cfg.data.param_id, rc);
rc = -EINVAL;
goto fail_cmd1;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
if (!rc) {
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
mfc_cfg.data.param_id);
rc = -ETIMEDOUT;
goto fail_cmd1;
}
if (atomic_read(&ac->cmd_state_pp) > 0) {
pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
__func__, adsp_err_get_err_str(
atomic_read(&ac->cmd_state_pp)),
mfc_cfg.data.param_id);
rc = adsp_err_get_lnx_err_code(
atomic_read(&ac->cmd_state_pp));
goto fail_cmd1;
}
variable_payload = pan_param->num_output_channels * sizeof(uint16_t)+
pan_param->num_input_channels * sizeof(uint16_t) +
pan_param->num_output_channels * sizeof(uint16_t) *
pan_param->num_input_channels * sizeof(uint16_t);
i = (variable_payload % sizeof(uint32_t));
variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i;
sz = sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2) +
sizeof(struct audproc_chmixer_param_coeff) +
variable_payload;
asm_params = kzalloc(sz, GFP_KERNEL);
if (!asm_params) {
rc = -ENOMEM;
goto fail_cmd1;
}
q6asm_add_hdr_async(ac, &hdr, sz, TRUE);
atomic_set(&ac->cmd_state_pp, -1);
hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr));
payload_params.data_payload_addr_lsw = 0;
payload_params.data_payload_addr_msw = 0;
payload_params.mem_map_handle = 0;
payload_params.data_payload_size =
sizeof(struct audproc_chmixer_param_coeff) +
variable_payload + sizeof(struct asm_stream_param_data_v2);
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)),
&payload_params,
sizeof(struct asm_stream_cmd_set_pp_params_v2));
data.module_id = AUDPROC_MODULE_ID_MFC;
data.param_id = AUDPROC_CHMIXER_PARAM_ID_COEFF;
data.param_size = sizeof(struct audproc_chmixer_param_coeff) +
variable_payload;
data.reserved = 0;
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2)),
&data, sizeof(struct asm_stream_param_data_v2));
pan_cfg.index = 0;
pan_cfg.num_output_channels = pan_param->num_output_channels;
pan_cfg.num_input_channels = pan_param->num_input_channels;
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2)),
&pan_cfg, sizeof(struct audproc_chmixer_param_coeff));
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2) +
sizeof(struct audproc_chmixer_param_coeff)),
pan_param->output_channel_map,
pan_param->num_output_channels * sizeof(uint16_t));
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2) +
sizeof(struct audproc_chmixer_param_coeff) +
pan_param->num_output_channels * sizeof(uint16_t)),
pan_param->input_channel_map,
pan_param->num_input_channels * sizeof(uint16_t));
memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2) +
sizeof(struct audproc_chmixer_param_coeff) +
(pan_param->num_output_channels * sizeof(uint16_t)) +
(pan_param->num_input_channels * sizeof(uint16_t))),
pan_param->gain,
(pan_param->num_output_channels * sizeof(uint16_t)) *
(pan_param->num_input_channels * sizeof(uint16_t)));
rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
if (rc < 0) {
pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
__func__, data.param_id, rc);
rc = -EINVAL;
goto fail_cmd2;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
if (!rc) {
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
data.param_id);
rc = -ETIMEDOUT;
goto fail_cmd2;
}
if (atomic_read(&ac->cmd_state_pp) > 0) {
pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
__func__, adsp_err_get_err_str(
atomic_read(&ac->cmd_state_pp)),
data.param_id);
rc = adsp_err_get_lnx_err_code(
atomic_read(&ac->cmd_state_pp));
goto fail_cmd2;
}
rc = 0;
fail_cmd2:
kfree(asm_params);
fail_cmd1:
return rc;
}
int q6asm_equalizer(struct audio_client *ac, void *eq_p)
{
struct asm_eq_params eq;