From defd81b1a54d4f515a6a02e5924b843322b08b2c Mon Sep 17 00:00:00 2001 From: Dhananjay Kumar Date: Tue, 11 Dec 2018 18:05:59 +0530 Subject: [PATCH] dsp: add support to set custom channel mixer coefficients Enhance Channel Mixer control for MultiMedia Frontends to get custom channel mixer coefficients from userspace and use it during device routings to control stream to device channel mappings. Change-Id: Ifedac25de5ae6bad1092b66ec405bba66a80f608 Signed-off-by: Cong Tang Signed-off-by: Dhananjay Kumar --- dsp/q6adm.c | 105 ++++++++++++----------------------------- dsp/q6asm.c | 14 ++++-- include/dsp/q6adm-v2.h | 8 +++- include/dsp/q6asm-v2.h | 6 ++- 4 files changed, 52 insertions(+), 81 deletions(-) diff --git a/dsp/q6adm.c b/dsp/q6adm.c index f905ef1ae65c..1851b9877357 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -141,6 +141,11 @@ void msm_dts_srs_release_lock(void) mutex_unlock(&dts_srs_lock); } +static int adm_arrange_mch_map_v8( + struct adm_device_endpoint_payload *ep_payload, + int path, + int channel_mode); + /** * adm_validate_and_get_port_index - * validate given port id @@ -488,9 +493,10 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL; struct param_hdr_v1 data_v5; int ret = 0, port_idx, sz = 0, param_size = 0; + struct adm_device_endpoint_payload ep_params = {0, 0, 0, {0}}; u16 *adm_pspd_params; u16 *ptr; - int index = 0; + int index = 0, i = 0, path_type = ADM_PATH_PLAYBACK; pr_debug("%s: port_id = %d\n", __func__, port_id); port_id = afe_convert_virtual_to_portid(port_id); @@ -515,7 +521,7 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, ch_mixer->input_channels[channel_index] + ch_mixer->input_channels[channel_index] * ch_mixer->output_channel); - roundup(param_size, 4); + param_size = roundup(param_size, 4); sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) + sizeof(struct default_chmixer_param_id_coeff) + @@ -561,84 +567,31 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, adm_pspd_params[3] = ch_mixer->input_channels[channel_index]; index = 4; - if (ch_mixer->output_channel == 1) { - adm_pspd_params[index] = PCM_CHANNEL_FC; - } else if (ch_mixer->output_channel == 2) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - } else if (ch_mixer->output_channel == 3) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - } else if (ch_mixer->output_channel == 4) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LS; - adm_pspd_params[index + 3] = PCM_CHANNEL_RS; - } else if (ch_mixer->output_channel == 5) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - adm_pspd_params[index + 3] = PCM_CHANNEL_LS; - adm_pspd_params[index + 4] = PCM_CHANNEL_RS; - } else if (ch_mixer->output_channel == 6) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - } else if (ch_mixer->output_channel == 8) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - adm_pspd_params[index + 6] = PCM_CHANNEL_LB; - adm_pspd_params[index + 7] = PCM_CHANNEL_RB; + path_type = (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) ? + ADM_PATH_PLAYBACK : ADM_PATH_LIVE_REC; + + if (ch_mixer->override_out_ch_map) { + memcpy(&adm_pspd_params[index], &ch_mixer->out_ch_map, + ch_mixer->output_channel * sizeof(uint16_t)); + index += ch_mixer->output_channel; + } else { + ep_params.dev_num_channel = ch_mixer->output_channel; + adm_arrange_mch_map_v8(&ep_params, path_type, ep_params.dev_num_channel); + for (i = 0; i < ch_mixer->output_channel; i++) + adm_pspd_params[index++] = ep_params.dev_channel_mapping[i]; } - index = index + ch_mixer->output_channel; - if (ch_mixer->input_channels[channel_index] == 1) { - adm_pspd_params[index] = PCM_CHANNEL_FC; - } else if (ch_mixer->input_channels[channel_index] == 2) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - } else if (ch_mixer->input_channels[channel_index] == 3) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - } else if (ch_mixer->input_channels[channel_index] == 4) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LS; - adm_pspd_params[index + 3] = PCM_CHANNEL_RS; - } else if (ch_mixer->input_channels[channel_index] == 5) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - adm_pspd_params[index + 3] = PCM_CHANNEL_LS; - adm_pspd_params[index + 4] = PCM_CHANNEL_RS; - } else if (ch_mixer->input_channels[channel_index] == 6) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - } else if (ch_mixer->input_channels[channel_index] == 8) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - adm_pspd_params[index + 6] = PCM_CHANNEL_LB; - adm_pspd_params[index + 7] = PCM_CHANNEL_RB; + if (ch_mixer->override_in_ch_map) { + memcpy(&adm_pspd_params[index], &ch_mixer->in_ch_map, + ch_mixer->input_channel * sizeof(uint16_t)); + index += ch_mixer->input_channel; + } else { + ep_params.dev_num_channel = ch_mixer->input_channels[channel_index]; + adm_arrange_mch_map_v8(&ep_params, path_type, ep_params.dev_num_channel); + for (i = 0; i < ch_mixer->input_channels[channel_index]; i++) + adm_pspd_params[index++] = ep_params.dev_channel_mapping[i]; } - index = index + ch_mixer->input_channels[channel_index]; ret = adm_populate_channel_weight(&adm_pspd_params[index], ch_mixer, channel_index); if (ret) { diff --git a/dsp/q6asm.c b/dsp/q6asm.c index 5c9de064feed..1b10d62b4af8 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -114,8 +114,6 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir); static void q6asm_reset_buf_state(struct audio_client *ac); -static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels, - bool use_back_flavor); void *q6asm_mmap_apr_reg(void); static int q6asm_is_valid_session(struct apr_client_data *data, void *priv); @@ -5420,7 +5418,16 @@ fail_cmd: } EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_native); -static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels, +/* + * q6asm_map_channels: + * Provide default asm channel mapping for given channel count. + * + * @channel_mapping: buffer pointer to write back channel maps. + * @channels: channel count for which channel map is required. + * @use_back_flavor: use back channels instead of surround channels. + * Returns 0 for success, -EINVAL for unsupported channel count. + */ +int q6asm_map_channels(u8 *channel_mapping, uint32_t channels, bool use_back_flavor) { u8 *lchannel_mapping; @@ -5528,6 +5535,7 @@ static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels, } return 0; } +EXPORT_SYMBOL(q6asm_map_channels); /** * q6asm_enable_sbrps - diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h index 3d60963a8493..b86175a002b4 100644 --- a/include/dsp/q6adm-v2.h +++ b/include/dsp/q6adm-v2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. */ #ifndef __Q6_ADM_V2_H__ #define __Q6_ADM_V2_H__ @@ -77,6 +77,12 @@ struct msm_pcm_channel_mixer { bool enable; int rule; int channel_weight[ADM_MAX_CHANNELS][ADM_MAX_CHANNELS]; + int port_idx; + int input_channel; + uint16_t in_ch_map[ADM_MAX_CHANNELS]; + uint16_t out_ch_map[ADM_MAX_CHANNELS]; + bool override_in_ch_map; + bool override_out_ch_map; }; int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id, diff --git a/include/dsp/q6asm-v2.h b/include/dsp/q6asm-v2.h index 4851a81ff023..1bb44b4a31d1 100644 --- a/include/dsp/q6asm-v2.h +++ b/include/dsp/q6asm-v2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. */ #ifndef __Q6_ASM_V2_H__ #define __Q6_ASM_V2_H__ @@ -741,4 +741,8 @@ uint8_t q6asm_get_stream_id_from_token(uint32_t token); int q6asm_adjust_session_clock(struct audio_client *ac, uint32_t adjust_time_lsw, uint32_t adjust_time_msw); + +/* Provide default asm channel mapping for given channel count */ +int q6asm_map_channels(u8 *channel_mapping, uint32_t channels, + bool use_back_flavor); #endif /* __Q6_ASM_H__ */