Merge "ASoc: msm: add support for mixing data from different COPPs"
This commit is contained in:
commit
ea7491238f
3 changed files with 992 additions and 1 deletions
|
@ -65,6 +65,20 @@ struct route_payload {
|
|||
unsigned int session_id;
|
||||
};
|
||||
|
||||
struct default_chmixer_param_id_coeff {
|
||||
uint32_t index;
|
||||
uint16_t num_output_channels;
|
||||
uint16_t num_input_channels;
|
||||
};
|
||||
|
||||
struct msm_pcm_channel_mixer {
|
||||
int output_channel;
|
||||
int input_channels[ADM_MAX_CHANNELS];
|
||||
bool enable;
|
||||
int rule;
|
||||
int channel_weight[ADM_MAX_CHANNELS][ADM_MAX_CHANNELS];
|
||||
};
|
||||
|
||||
int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
|
||||
void *srs_params);
|
||||
|
||||
|
@ -166,4 +180,8 @@ int adm_get_source_tracking(int port_id, int copp_idx,
|
|||
struct source_tracking_param *sourceTrackingData);
|
||||
int adm_swap_speaker_channels(int port_id, int copp_idx, int sample_rate,
|
||||
bool spk_swap);
|
||||
int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
|
||||
int session_type,
|
||||
struct msm_pcm_channel_mixer *ch_mixer,
|
||||
int channel_index);
|
||||
#endif /* __Q6_ADM_V2_H__ */
|
||||
|
|
|
@ -81,6 +81,12 @@ static bool is_custom_stereo_on;
|
|||
static bool is_ds2_on;
|
||||
static bool swap_ch;
|
||||
|
||||
#define WEIGHT_0_DB 0x4000
|
||||
/* all the FEs which can support channel mixer */
|
||||
static struct msm_pcm_channel_mixer channel_mixer[MSM_FRONTEND_DAI_MM_SIZE];
|
||||
/* input BE for each FE */
|
||||
static int channel_input[MSM_FRONTEND_DAI_MM_SIZE][ADM_MAX_CHANNELS];
|
||||
|
||||
enum {
|
||||
MADNONE,
|
||||
MADAUDIO,
|
||||
|
@ -1257,6 +1263,62 @@ static u32 msm_pcm_routing_get_voc_sessionid(u16 val)
|
|||
return session_id;
|
||||
}
|
||||
|
||||
static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode,
|
||||
int dspst_id, int stream_type)
|
||||
{
|
||||
int copp_idx = 0;
|
||||
int sess_type = 0;
|
||||
int i = 0, j = 0, be_id;
|
||||
int ret = 0;
|
||||
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(channel_mixer[fe_id].enable)) {
|
||||
pr_debug("%s: channel mixer not enabled for FE %d\n",
|
||||
__func__, fe_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_type == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
sess_type = SESSION_TYPE_RX;
|
||||
else
|
||||
sess_type = SESSION_TYPE_TX;
|
||||
|
||||
for (i = 0; i < ADM_MAX_CHANNELS && channel_input[fe_id][i] > 0;
|
||||
++i) {
|
||||
be_id = channel_input[fe_id][i] - 1;
|
||||
channel_mixer[fe_id].input_channels[i] =
|
||||
msm_bedais[be_id].channel;
|
||||
|
||||
if ((msm_bedais[be_id].active) &&
|
||||
test_bit(fe_id,
|
||||
&msm_bedais[be_id].fe_sessions[0])) {
|
||||
unsigned long copp =
|
||||
session_copp_map[fe_id][sess_type][be_id];
|
||||
for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
|
||||
if (test_bit(j, &copp)) {
|
||||
copp_idx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pr_debug("%s: fe %d, be %d, channel %d, copp %d\n",
|
||||
__func__,
|
||||
fe_id, be_id, msm_bedais[be_id].channel,
|
||||
copp_idx);
|
||||
ret = adm_programable_channel_mixer(
|
||||
msm_bedais[be_id].port_id,
|
||||
copp_idx, dspst_id, sess_type,
|
||||
channel_mixer + fe_id, i);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
|
||||
int dspst_id, int stream_type)
|
||||
{
|
||||
|
@ -1265,6 +1327,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
|
|||
u32 channels, sample_rate;
|
||||
uint16_t bits_per_sample = 16;
|
||||
uint32_t passthr_mode = LEGACY_PCM;
|
||||
int ret = 0;
|
||||
|
||||
if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
|
||||
/* bad ID assigned in machine driver */
|
||||
|
@ -1388,8 +1451,11 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
|
|||
adm_matrix_map(path_type, payload, perf_mode, passthr_mode);
|
||||
msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode);
|
||||
}
|
||||
|
||||
ret = msm_pcm_routing_channel_mixer(fedai_id, perf_mode,
|
||||
dspst_id, stream_type);
|
||||
mutex_unlock(&routing_lock);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int msm_pcm_routing_reg_phy_stream_v2(int fedai_id, int perf_mode,
|
||||
|
@ -2614,6 +2680,649 @@ static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int msm_pcm_get_channel_rule_index(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0;
|
||||
|
||||
fe_id = ((struct soc_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ucontrol->value.integer.value[0] = channel_mixer[fe_id].rule;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_put_channel_rule_index(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0;
|
||||
|
||||
fe_id = ((struct soc_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel_mixer[fe_id].rule = ucontrol->value.integer.value[0];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int msm_pcm_get_out_chs(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0;
|
||||
|
||||
fe_id = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ucontrol->value.integer.value[0] =
|
||||
channel_mixer[fe_id].output_channel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_put_out_chs(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0;
|
||||
|
||||
fe_id = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("%s: fe_id is %d, output channels = %d\n", __func__,
|
||||
fe_id,
|
||||
(unsigned int)(ucontrol->value.integer.value[0]));
|
||||
channel_mixer[fe_id].output_channel =
|
||||
(unsigned int)(ucontrol->value.integer.value[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *const ch_mixer[] = {"Disable", "Enable"};
|
||||
|
||||
/* If new backend is added, need update this array */
|
||||
static const char *const be_name[] = {
|
||||
"ZERO", "PRI_I2S_RX", "PRI_I2S_TX", "SLIM_0_RX",
|
||||
"SLIM_0_TX", "HDMI_RX", "INT_BT_SCO_RX", "INT_BT_SCO_TX",
|
||||
"INT_FM_RX", "INT_FM_TX", "AFE_PCM_RX", "AFE_PCM_TX",
|
||||
"AUXPCM_RX", "AUXPCM_TX", "VOICE_PLAYBACK_TX", "VOICE2_PLAYBACK_TX",
|
||||
"INCALL_RECORD_RX", "INCALL_RECORD_TX", "MI2S_RX", "MI2S_TX",
|
||||
"SEC_I2S_RX", "SLIM_1_RX", "SLIM_1_TX", "SLIM_2_RX",
|
||||
"SLIM_2_TX", "SLIM_3_RX", "SLIM_3_TX", "SLIM_4_RX",
|
||||
"SLIM_4_TX", "SLIM_5_RX", "SLIM_5_TX", "SLIM_6_RX",
|
||||
"SLIM_6_TX", "SLIM_7_RX", "SLIM_7_TX", "SLIM_8_RX",
|
||||
"SLIM_8_TX", "EXTPROC_RX", "EXTPROC_TX", "EXPROC_EC_TX",
|
||||
"QUAT_MI2S_RX", "QUAT_MI2S_TX", "SECOND_MI2S_RX", "SECOND_MI2S_TX",
|
||||
"PRI_MI2S_RX", "PRI_MI2S_TX", "TERT_MI2S_RX", "TERT_MI2S_TX",
|
||||
"AUDIO_I2S_RX", "SEC_AUXPCM_RX", "SEC_AUXPCM_TX", "SPDIF_RX",
|
||||
"SECOND_MI2S_RX_SD1", "QUIN_MI2S_RX", "QUIN_MI2S_TX", "SENARY_MI2S_TX",
|
||||
"PRI_TDM_RX_0", "PRI_TDM_TX_0", "PRI_TDM_RX_1", "PRI_TDM_TX_1",
|
||||
"PRI_TDM_RX_2", "PRI_TDM_TX_2", "PRI_TDM_RX_3", "PRI_TDM_TX_3",
|
||||
"PRI_TDM_RX_4", "PRI_TDM_TX_4", "PRI_TDM_RX_5", "PRI_TDM_TX_5",
|
||||
"PRI_TDM_RX_6", "PRI_TDM_TX_6", "PRI_TDM_RX_7", "PRI_TDM_TX_7",
|
||||
"SEC_TDM_RX_0", "SEC_TDM_TX_0", "SEC_TDM_RX_1", "SEC_TDM_TX_1",
|
||||
"SEC_TDM_RX_2", "SEC_TDM_TX_2", "SEC_TDM_RX_3", "SEC_TDM_TX_3",
|
||||
"SEC_TDM_RX_4", "SEC_TDM_TX_4", "SEC_TDM_RX_5", "SEC_TDM_TX_5",
|
||||
"SEC_TDM_RX_6", "SEC_TDM_TX_6", "SEC_TDM_RX_7", "SEC_TDM_TX_7",
|
||||
"TERT_TDM_RX_0", "TERT_TDM_TX_0", "TERT_TDM_RX_1", "TERT_TDM_TX_1",
|
||||
"TERT_TDM_RX_2", "TERT_TDM_TX_2", "TERT_TDM_RX_3", "TERT_TDM_TX_3",
|
||||
"TERT_TDM_RX_4", "TERT_TDM_TX_4", "TERT_TDM_RX_5", "TERT_TDM_TX_5",
|
||||
"TERT_TDM_RX_6", "TERT_TDM_TX_6", "TERT_TDM_RX_7", "TERT_TDM_TX_7",
|
||||
"QUAT_TDM_RX_0", "QUAT_TDM_TX_0", "QUAT_TDM_RX_1", "QUAT_TDM_TX_1",
|
||||
"QUAT_TDM_RX_2", "QUAT_TDM_TX_2", "QUAT_TDM_RX_3", "QUAT_TDM_TX_3",
|
||||
"QUAT_TDM_RX_4", "QUAT_TDM_TX_4", "QUAT_TDM_RX_5", "QUAT_TDM_TX_5",
|
||||
"QUAT_TDM_RX_6", "QUAT_TDM_TX_6", "QUAT_TDM_RX_7", "QUAT_TDM_TX_7",
|
||||
"INT_BT_A2DP_RX", "USB_RX", "USB_TX", "DISPLAY_PORT_RX",
|
||||
"TERT_AUXPCM_RX", "TERT_AUXPCM_TX", "QUAT_AUXPCM_RX", "QUAT_AUXPCM_TX",
|
||||
"INT0_MI2S_RX", "INT0_MI2S_TX", "INT1_MI2S_RX", "INT1_MI2S_TX",
|
||||
"INT2_MI2S_RX", "INT2_MI2S_TX", "INT3_MI2S_RX", "INT3_MI2S_TX",
|
||||
"INT4_MI2S_RX", "INT4_MI2S_TX", "INT5_MI2S_RX", "INT5_MI2S_TX",
|
||||
"INT6_MI2S_RX", "INT6_MI2S_TX"
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(mm1_channel_mux,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, ch_mixer);
|
||||
static SOC_ENUM_SINGLE_DECL(mm2_channel_mux,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA2, ch_mixer);
|
||||
static SOC_ENUM_SINGLE_DECL(mm3_channel_mux,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA3, ch_mixer);
|
||||
static SOC_ENUM_SINGLE_DECL(mm4_channel_mux,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA4, ch_mixer);
|
||||
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch1_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 0, be_name);
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch2_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, be_name);
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch3_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 2, be_name);
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch4_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 3, be_name);
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch5_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 4, be_name);
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch6_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 5, be_name);
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch7_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 6, be_name);
|
||||
static SOC_ENUM_DOUBLE_DECL(mm1_ch8_enum,
|
||||
SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 7, be_name);
|
||||
|
||||
static int msm_pcm_get_ctl_enum_info(struct snd_ctl_elem_info *uinfo,
|
||||
unsigned int channels,
|
||||
unsigned int items, const char *const names[])
|
||||
{
|
||||
if (uinfo->value.enumerated.item >= items)
|
||||
uinfo->value.enumerated.item = items - 1;
|
||||
|
||||
WARN(strlen(names[uinfo->value.enumerated.item]) >=
|
||||
sizeof(uinfo->value.enumerated.name),
|
||||
"ALSA: too long item name '%s'\n",
|
||||
names[uinfo->value.enumerated.item]);
|
||||
strlcpy(uinfo->value.enumerated.name,
|
||||
names[uinfo->value.enumerated.item],
|
||||
sizeof(uinfo->value.enumerated.name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_mixer_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
uinfo->count = 1;
|
||||
|
||||
uinfo->value.enumerated.items = ARRAY_SIZE(ch_mixer);
|
||||
msm_pcm_get_ctl_enum_info(uinfo, 1, e->items, e->texts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int msm_pcm_channel_mixer_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0;
|
||||
|
||||
fe_id = ((struct soc_enum *)
|
||||
kcontrol->private_value)->shift_l;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("%s: FE %d %s\n", __func__,
|
||||
fe_id,
|
||||
channel_mixer[fe_id].enable ? "Enabled" : "Disabled");
|
||||
ucontrol->value.enumerated.item[0] = channel_mixer[fe_id].enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_mixer_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0;
|
||||
|
||||
fe_id = ((struct soc_enum *)
|
||||
kcontrol->private_value)->shift_l;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel_mixer[fe_id].enable = ucontrol->value.enumerated.item[0];
|
||||
pr_debug("%s: %s FE %d\n", __func__,
|
||||
channel_mixer[fe_id].enable ? "Enable" : "Disable",
|
||||
fe_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_input_be_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||
uinfo->count = 1;
|
||||
|
||||
uinfo->value.enumerated.items = ARRAY_SIZE(be_name);
|
||||
msm_pcm_get_ctl_enum_info(uinfo, 1, e->items, e->texts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_input_be_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
u16 fe_id = 0, in_ch = 0;
|
||||
|
||||
fe_id = e->shift_l;
|
||||
in_ch = e->shift_r;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (in_ch >= ADM_MAX_CHANNELS) {
|
||||
pr_err("%s: invalid input channel %d\n", __func__, in_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel_input[fe_id][in_ch] = ucontrol->value.enumerated.item[0];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_input_be_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
||||
u16 fe_id = 0, in_ch = 0;
|
||||
|
||||
fe_id = e->shift_l;
|
||||
in_ch = e->shift_r;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (in_ch >= ADM_MAX_CHANNELS) {
|
||||
pr_err("%s: invalid input channel %d\n", __func__, in_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ucontrol->value.enumerated.item[0] = channel_input[fe_id][in_ch];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int msm_pcm_channel_weight_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = ADM_MAX_CHANNELS;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = WEIGHT_0_DB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_weight_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0, out_ch = 0;
|
||||
int i, weight;
|
||||
|
||||
fe_id = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
out_ch = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->rshift;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (out_ch >= ADM_MAX_CHANNELS) {
|
||||
pr_err("%s: invalid input channel %d\n", __func__, out_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("%s: FE_ID: %d, channel weight %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld\n",
|
||||
__func__, fe_id,
|
||||
ucontrol->value.integer.value[0],
|
||||
ucontrol->value.integer.value[1],
|
||||
ucontrol->value.integer.value[2],
|
||||
ucontrol->value.integer.value[3],
|
||||
ucontrol->value.integer.value[4],
|
||||
ucontrol->value.integer.value[5],
|
||||
ucontrol->value.integer.value[6],
|
||||
ucontrol->value.integer.value[7]);
|
||||
|
||||
for (i = 0; i < ADM_MAX_CHANNELS; ++i) {
|
||||
weight = ucontrol->value.integer.value[i];
|
||||
channel_mixer[fe_id].channel_weight[out_ch][i] = weight;
|
||||
pr_debug("%s: FE_ID %d, output %d input %d weight %d\n",
|
||||
__func__, fe_id, out_ch, i,
|
||||
channel_mixer[fe_id].channel_weight[out_ch][i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_weight_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
u16 fe_id = 0, out_ch = 0;
|
||||
int i;
|
||||
|
||||
fe_id = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->shift;
|
||||
out_ch = ((struct soc_multi_mixer_control *)
|
||||
kcontrol->private_value)->rshift;
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %d\n", __func__, fe_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (out_ch >= ADM_MAX_CHANNELS) {
|
||||
pr_err("%s: invalid input channel %d\n", __func__, out_ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ADM_MAX_CHANNELS; ++i)
|
||||
ucontrol->value.integer.value[i] =
|
||||
channel_mixer[fe_id].channel_weight[out_ch][i];
|
||||
|
||||
pr_debug("%s: FE_ID: %d, weight %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld",
|
||||
__func__, fe_id,
|
||||
ucontrol->value.integer.value[0],
|
||||
ucontrol->value.integer.value[1],
|
||||
ucontrol->value.integer.value[2],
|
||||
ucontrol->value.integer.value[3],
|
||||
ucontrol->value.integer.value[4],
|
||||
ucontrol->value.integer.value[5],
|
||||
ucontrol->value.integer.value[6],
|
||||
ucontrol->value.integer.value[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new channel_mixer_controls[] = {
|
||||
SOC_SINGLE_EXT("MultiMedia1 Channel Rule", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA1, 8, 0,
|
||||
msm_pcm_get_channel_rule_index,
|
||||
msm_pcm_put_channel_rule_index),
|
||||
SOC_SINGLE_EXT("MultiMedia2 Channel Rule", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA2, 8, 0,
|
||||
msm_pcm_get_channel_rule_index,
|
||||
msm_pcm_put_channel_rule_index),
|
||||
SOC_SINGLE_EXT("MultiMedia3 Channel Rule", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA3, 8, 0,
|
||||
msm_pcm_get_channel_rule_index,
|
||||
msm_pcm_put_channel_rule_index),
|
||||
SOC_SINGLE_EXT("MultiMedia4 Channel Rule", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA4, 8, 0,
|
||||
msm_pcm_get_channel_rule_index,
|
||||
msm_pcm_put_channel_rule_index),
|
||||
SOC_SINGLE_EXT("MultiMedia5 Channel Rule", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA5, 8, 0,
|
||||
msm_pcm_get_channel_rule_index,
|
||||
msm_pcm_put_channel_rule_index),
|
||||
SOC_SINGLE_EXT("MultiMedia6 Channel Rule", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA6, 8, 0,
|
||||
msm_pcm_get_channel_rule_index,
|
||||
msm_pcm_put_channel_rule_index),
|
||||
|
||||
SOC_SINGLE_EXT("MultiMedia1 Channels", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA1, 8, 0,
|
||||
msm_pcm_get_out_chs,
|
||||
msm_pcm_put_out_chs),
|
||||
SOC_SINGLE_EXT("MultiMedia2 Channels", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA2, 8, 0,
|
||||
msm_pcm_get_out_chs,
|
||||
msm_pcm_put_out_chs),
|
||||
SOC_SINGLE_EXT("MultiMedia3 Channels", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA3, 8, 0,
|
||||
msm_pcm_get_out_chs,
|
||||
msm_pcm_put_out_chs),
|
||||
SOC_SINGLE_EXT("MultiMedia4 Channels", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA4, 8, 0,
|
||||
msm_pcm_get_out_chs,
|
||||
msm_pcm_put_out_chs),
|
||||
SOC_SINGLE_EXT("MultiMedia5 Channels", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA5, 8, 0,
|
||||
msm_pcm_get_out_chs,
|
||||
msm_pcm_put_out_chs),
|
||||
SOC_SINGLE_EXT("MultiMedia6 Channels", SND_SOC_NOPM,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA6, 8, 0,
|
||||
msm_pcm_get_out_chs,
|
||||
msm_pcm_put_out_chs),
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel Mixer",
|
||||
.info = msm_pcm_channel_mixer_info,
|
||||
.get = msm_pcm_channel_mixer_get,
|
||||
.put = msm_pcm_channel_mixer_put,
|
||||
.private_value = (unsigned long)&(mm1_channel_mux)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia2 Channel Mixer",
|
||||
.info = msm_pcm_channel_mixer_info,
|
||||
.get = msm_pcm_channel_mixer_get,
|
||||
.put = msm_pcm_channel_mixer_put,
|
||||
.private_value = (unsigned long)&(mm2_channel_mux)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia3 Channel Mixer",
|
||||
.info = msm_pcm_channel_mixer_info,
|
||||
.get = msm_pcm_channel_mixer_get,
|
||||
.put = msm_pcm_channel_mixer_put,
|
||||
.private_value = (unsigned long)&(mm3_channel_mux)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia4 Channel Mixer",
|
||||
.info = msm_pcm_channel_mixer_info,
|
||||
.get = msm_pcm_channel_mixer_get,
|
||||
.put = msm_pcm_channel_mixer_put,
|
||||
.private_value = (unsigned long)&(mm4_channel_mux)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel1",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 0,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel2",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 1, }
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel3",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 2,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel4",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 3,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel5",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 4,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel6",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 5,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel7",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 6,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Output Channel8",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{ .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 7,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia2 Output Channel1",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{.shift = MSM_FRONTEND_DAI_MULTIMEDIA2, .rshift = 0,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia2 Output Channel2",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{.shift = MSM_FRONTEND_DAI_MULTIMEDIA2, .rshift = 1,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia2 Output Channel3",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{.shift = MSM_FRONTEND_DAI_MULTIMEDIA2, .rshift = 2,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia3 Output Channel1",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{.shift = MSM_FRONTEND_DAI_MULTIMEDIA3, .rshift = 0,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia3 Output Channel2",
|
||||
.info = msm_pcm_channel_weight_info,
|
||||
.get = msm_pcm_channel_weight_get,
|
||||
.put = msm_pcm_channel_weight_put,
|
||||
.private_value = (unsigned long)&(struct soc_multi_mixer_control)
|
||||
{.shift = MSM_FRONTEND_DAI_MULTIMEDIA3, .rshift = 1,}
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel1",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch1_enum)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel2",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch2_enum)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel3",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch3_enum)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel4",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch4_enum)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel5",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch5_enum)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel6",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch6_enum)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel7",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch7_enum)
|
||||
},
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.name = "MultiMedia1 Channel8",
|
||||
.info = msm_pcm_channel_input_be_info,
|
||||
.get = msm_pcm_channel_input_be_get,
|
||||
.put = msm_pcm_channel_input_be_put,
|
||||
.private_value = (unsigned long)&(mm1_ch8_enum)
|
||||
},
|
||||
};
|
||||
static int msm_ec_ref_ch_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
@ -14809,6 +15518,9 @@ static int msm_routing_probe(struct snd_soc_platform *platform)
|
|||
snd_soc_add_platform_controls(platform, ec_ref_param_controls,
|
||||
ARRAY_SIZE(ec_ref_param_controls));
|
||||
|
||||
snd_soc_add_platform_controls(platform, channel_mixer_controls,
|
||||
ARRAY_SIZE(channel_mixer_controls));
|
||||
|
||||
msm_qti_pp_add_controls(platform);
|
||||
|
||||
msm_dts_srs_tm_add_controls(platform);
|
||||
|
|
|
@ -520,6 +520,267 @@ fail_cmd:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int adm_populate_channel_weight(u16 *ptr,
|
||||
struct msm_pcm_channel_mixer *ch_mixer,
|
||||
int channel_index)
|
||||
{
|
||||
u16 i, j, start_index = 0;
|
||||
|
||||
if (channel_index > ch_mixer->output_channel) {
|
||||
pr_err("%s: channel index %d is larger than output_channel %d\n",
|
||||
__func__, channel_index, ch_mixer->output_channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ch_mixer->output_channel; i++) {
|
||||
pr_debug("%s: weight for output %d:", __func__, i);
|
||||
for (j = 0; j < ADM_MAX_CHANNELS; j++)
|
||||
pr_debug(" %d",
|
||||
ch_mixer->channel_weight[i][j]);
|
||||
pr_debug("\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < channel_index; ++i)
|
||||
start_index += ch_mixer->input_channels[i];
|
||||
|
||||
for (i = 0; i < ch_mixer->output_channel; ++i) {
|
||||
for (j = start_index;
|
||||
j < start_index +
|
||||
ch_mixer->input_channels[channel_index]; j++) {
|
||||
*ptr = ch_mixer->channel_weight[i][j];
|
||||
pr_debug("%s: ptr[%d][%d] = %d\n",
|
||||
__func__, i, j, *ptr);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* adm_programable_channel_mixer
|
||||
*
|
||||
* Receives port_id, copp_idx, session_id, session_type, ch_mixer
|
||||
* and channel_index to send ADM command to mix COPP data.
|
||||
*
|
||||
* port_id - Passed value, port_id for which backend is wanted
|
||||
* copp_idx - Passed value, copp_idx for which COPP is wanted
|
||||
* session_id - Passed value, session_id for which session is needed
|
||||
* session_type - Passed value, session_type for RX or TX
|
||||
* ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
|
||||
* channel_index - Passed value, channel_index for which channel is needed
|
||||
*/
|
||||
int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
|
||||
int session_type,
|
||||
struct msm_pcm_channel_mixer *ch_mixer,
|
||||
int channel_index)
|
||||
{
|
||||
struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
|
||||
struct adm_param_data_v5 data_v5;
|
||||
int ret = 0, port_idx, sz = 0, param_size = 0;
|
||||
u16 *adm_pspd_params;
|
||||
u16 *ptr;
|
||||
int index = 0;
|
||||
|
||||
pr_debug("%s: port_id = %d\n", __func__, port_id);
|
||||
port_id = afe_convert_virtual_to_portid(port_id);
|
||||
port_idx = adm_validate_and_get_port_index(port_id);
|
||||
if (port_idx < 0) {
|
||||
pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* First 8 bytes are 4 bytes as rule number, 2 bytes as output
|
||||
* channel and 2 bytes as input channel.
|
||||
* 2 * ch_mixer->output_channel means output channel mapping.
|
||||
* 2 * ch_mixer->input_channels[channel_index]) means input
|
||||
* channel mapping.
|
||||
* 2 * ch_mixer->input_channels[channel_index] *
|
||||
* ch_mixer->output_channel) means the channel mixer weighting
|
||||
* coefficients.
|
||||
* param_size needs to be a multiple of 4 bytes.
|
||||
*/
|
||||
|
||||
param_size = 2 * (4 + ch_mixer->output_channel +
|
||||
ch_mixer->input_channels[channel_index] +
|
||||
ch_mixer->input_channels[channel_index] *
|
||||
ch_mixer->output_channel);
|
||||
roundup(param_size, 4);
|
||||
|
||||
sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
|
||||
sizeof(struct default_chmixer_param_id_coeff) +
|
||||
sizeof(struct adm_param_data_v5) + param_size;
|
||||
pr_debug("%s: sz = %d\n", __func__, sz);
|
||||
adm_params = kzalloc(sz, GFP_KERNEL);
|
||||
if (!adm_params)
|
||||
return -ENOMEM;
|
||||
|
||||
adm_params->payload_addr_lsw = 0;
|
||||
adm_params->payload_addr_msw = 0;
|
||||
adm_params->mem_map_handle = 0;
|
||||
adm_params->direction = session_type;
|
||||
adm_params->sessionid = session_id;
|
||||
pr_debug("%s: copp_id = %d, session id %d\n", __func__,
|
||||
atomic_read(&this_adm.copp.id[port_idx][copp_idx]),
|
||||
session_id);
|
||||
adm_params->deviceid = atomic_read(
|
||||
&this_adm.copp.id[port_idx][copp_idx]);
|
||||
adm_params->reserved = 0;
|
||||
|
||||
data_v5.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
|
||||
data_v5.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
|
||||
data_v5.reserved = 0;
|
||||
data_v5.param_size = param_size;
|
||||
adm_params->payload_size =
|
||||
sizeof(struct default_chmixer_param_id_coeff) +
|
||||
sizeof(struct adm_param_data_v5) + data_v5.param_size;
|
||||
adm_pspd_params = (u16 *)((u8 *)adm_params +
|
||||
sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5));
|
||||
memcpy(adm_pspd_params, &data_v5, sizeof(data_v5));
|
||||
|
||||
adm_pspd_params = (u16 *)((u8 *)adm_params +
|
||||
sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)
|
||||
+ sizeof(data_v5));
|
||||
|
||||
adm_pspd_params[0] = ch_mixer->rule;
|
||||
adm_pspd_params[2] = ch_mixer->output_channel;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
index = index + ch_mixer->input_channels[channel_index];
|
||||
ret = adm_populate_channel_weight(&adm_pspd_params[index],
|
||||
ch_mixer, channel_index);
|
||||
if (!ret) {
|
||||
pr_err("%s: fail to get channel weight with error %d\n",
|
||||
__func__, ret);
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
||||
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
|
||||
adm_params->hdr.src_svc = APR_SVC_ADM;
|
||||
adm_params->hdr.src_domain = APR_DOMAIN_APPS;
|
||||
adm_params->hdr.src_port = port_id;
|
||||
adm_params->hdr.dest_svc = APR_SVC_ADM;
|
||||
adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
|
||||
adm_params->hdr.dest_port =
|
||||
atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
|
||||
adm_params->hdr.token = port_idx << 16 | copp_idx;
|
||||
adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
|
||||
adm_params->hdr.pkt_size = sz;
|
||||
adm_params->payload_addr_lsw = 0;
|
||||
adm_params->payload_addr_msw = 0;
|
||||
adm_params->mem_map_handle = 0;
|
||||
adm_params->reserved = 0;
|
||||
|
||||
ptr = (u16 *)adm_params;
|
||||
for (index = 0; index < (sz / 2); index++)
|
||||
pr_debug("%s: adm_params[%d] = 0x%x\n",
|
||||
__func__, index, (unsigned int)ptr[index]);
|
||||
|
||||
atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0);
|
||||
ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Set params failed port %d rc %d\n", __func__,
|
||||
port_id, ret);
|
||||
ret = -EINVAL;
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
|
||||
atomic_read(
|
||||
&this_adm.copp.stat[port_idx][copp_idx]) >= 0,
|
||||
msecs_to_jiffies(TIMEOUT_MS));
|
||||
if (!ret) {
|
||||
pr_err("%s: set params timed out port = %d\n",
|
||||
__func__, port_id);
|
||||
ret = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
ret = 0;
|
||||
fail_cmd:
|
||||
kfree(adm_params);
|
||||
|
||||
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue