Merge "ASoC: msm: qdsp6v2: Add support for speaker swap"
This commit is contained in:
commit
fa3c35e909
3 changed files with 196 additions and 0 deletions
|
@ -164,4 +164,6 @@ int adm_get_sound_focus(int port_id, int copp_idx,
|
|||
struct sound_focus_param *soundFocusData);
|
||||
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);
|
||||
#endif /* __Q6_ADM_V2_H__ */
|
||||
|
|
|
@ -80,6 +80,7 @@ static uint32_t voc_session_id = ALL_SESSION_VSID;
|
|||
static int msm_route_ext_ec_ref;
|
||||
static bool is_custom_stereo_on;
|
||||
static bool is_ds2_on;
|
||||
static bool swap_ch;
|
||||
|
||||
enum {
|
||||
MADNONE,
|
||||
|
@ -14567,6 +14568,67 @@ static const struct snd_kcontrol_new
|
|||
},
|
||||
};
|
||||
|
||||
static int msm_routing_stereo_channel_reverse_control_get(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.integer.value[0] = swap_ch;
|
||||
pr_debug("%s: Swap channel value: %ld\n", __func__,
|
||||
ucontrol->value.integer.value[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_routing_stereo_channel_reverse_control_put(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int i, idx, be_index, port_id;
|
||||
int ret = 0;
|
||||
unsigned long copp;
|
||||
|
||||
pr_debug("%s Swap channel value:%ld\n", __func__,
|
||||
ucontrol->value.integer.value[0]);
|
||||
|
||||
swap_ch = ucontrol->value.integer.value[0];
|
||||
|
||||
mutex_lock(&routing_lock);
|
||||
for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) {
|
||||
port_id = msm_bedais[be_index].port_id;
|
||||
if (!msm_bedais[be_index].active)
|
||||
continue;
|
||||
|
||||
for_each_set_bit(i, &msm_bedais[be_index].fe_sessions[0],
|
||||
MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
copp = session_copp_map[i][SESSION_TYPE_RX][be_index];
|
||||
for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
|
||||
if (!test_bit(idx, &copp))
|
||||
continue;
|
||||
|
||||
pr_debug("%s: swap channel control of portid:%d, coppid:%d\n",
|
||||
__func__, port_id, idx);
|
||||
ret = adm_swap_speaker_channels(
|
||||
port_id, idx,
|
||||
msm_bedais[be_index].sample_rate,
|
||||
swap_ch);
|
||||
if (ret) {
|
||||
pr_err("%s:Swap_channel failed, err=%d\n",
|
||||
__func__, ret);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
mutex_unlock(&routing_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new stereo_channel_reverse_control[] = {
|
||||
SOC_SINGLE_EXT("Swap channel", SND_SOC_NOPM, 0,
|
||||
1, 0, msm_routing_stereo_channel_reverse_control_get,
|
||||
msm_routing_stereo_channel_reverse_control_put),
|
||||
};
|
||||
|
||||
static struct snd_pcm_ops msm_routing_pcm_ops = {
|
||||
.hw_params = msm_pcm_routing_hw_params,
|
||||
.close = msm_pcm_routing_close,
|
||||
|
@ -14632,6 +14694,8 @@ static int msm_routing_probe(struct snd_soc_platform *platform)
|
|||
|
||||
snd_soc_add_platform_controls(platform, aptx_dec_license_controls,
|
||||
ARRAY_SIZE(aptx_dec_license_controls));
|
||||
snd_soc_add_platform_controls(platform, stereo_channel_reverse_control,
|
||||
ARRAY_SIZE(stereo_channel_reverse_control));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -4288,6 +4288,136 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* adm_swap_speaker_channels
|
||||
*
|
||||
* Receives port_id, copp_idx, sample rate, spk_swap and
|
||||
* send MFC command to swap speaker channel.
|
||||
* Return zero on success. On failure returns nonzero.
|
||||
*
|
||||
* port_id - Passed value, port_id for which channels swap is wanted
|
||||
* copp_idx - Passed value, copp_idx for which channels swap is wanted
|
||||
* sample_rate - Passed value, sample rate used by app type config
|
||||
* spk_swap - Passed value, spk_swap for check if swap flag is set
|
||||
*/
|
||||
int adm_swap_speaker_channels(int port_id, int copp_idx,
|
||||
int sample_rate, bool spk_swap)
|
||||
{
|
||||
struct audproc_mfc_output_media_fmt mfc_cfg;
|
||||
uint16_t num_channels;
|
||||
int port_idx;
|
||||
int ret = 0;
|
||||
|
||||
pr_debug("%s: Enter, port_id %d, copp_idx %d\n",
|
||||
__func__, port_id, copp_idx);
|
||||
port_id = q6audio_convert_virtual_to_portid(port_id);
|
||||
port_idx = adm_validate_and_get_port_index(port_id);
|
||||
if (port_idx < 0 || port_idx >= AFE_MAX_PORTS) {
|
||||
pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) {
|
||||
pr_err("%s: Invalid copp_num: %d\n", __func__, copp_idx);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
num_channels = atomic_read(
|
||||
&this_adm.copp.channels[port_idx][copp_idx]);
|
||||
if (num_channels != 2) {
|
||||
pr_debug("%s: Invalid number of channels: %d\n",
|
||||
__func__, num_channels);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(&mfc_cfg, 0, sizeof(mfc_cfg));
|
||||
mfc_cfg.params.hdr.hdr_field =
|
||||
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
||||
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
|
||||
mfc_cfg.params.hdr.pkt_size =
|
||||
sizeof(mfc_cfg);
|
||||
mfc_cfg.params.hdr.src_svc = APR_SVC_ADM;
|
||||
mfc_cfg.params.hdr.src_domain = APR_DOMAIN_APPS;
|
||||
mfc_cfg.params.hdr.src_port = port_id;
|
||||
mfc_cfg.params.hdr.dest_svc = APR_SVC_ADM;
|
||||
mfc_cfg.params.hdr.dest_domain = APR_DOMAIN_ADSP;
|
||||
mfc_cfg.params.hdr.dest_port =
|
||||
atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
|
||||
mfc_cfg.params.hdr.token = port_idx << 16 | copp_idx;
|
||||
mfc_cfg.params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
|
||||
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 = sample_rate;
|
||||
mfc_cfg.bits_per_sample =
|
||||
atomic_read(&this_adm.copp.bit_width[port_idx][copp_idx]);
|
||||
mfc_cfg.num_channels = num_channels;
|
||||
|
||||
/* Currently applying speaker swap for only 2 channel use case */
|
||||
if (spk_swap) {
|
||||
mfc_cfg.channel_type[0] =
|
||||
(uint16_t) PCM_CHANNEL_FR;
|
||||
mfc_cfg.channel_type[1] =
|
||||
(uint16_t) PCM_CHANNEL_FL;
|
||||
} else {
|
||||
mfc_cfg.channel_type[0] =
|
||||
(uint16_t) PCM_CHANNEL_FL;
|
||||
mfc_cfg.channel_type[1] =
|
||||
(uint16_t) PCM_CHANNEL_FR;
|
||||
}
|
||||
|
||||
atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1);
|
||||
pr_debug("%s: mfc config: port_idx %d copp_idx %d copp SR %d copp BW %d copp chan %d\n",
|
||||
__func__, port_idx, copp_idx, mfc_cfg.sampling_rate,
|
||||
mfc_cfg.bits_per_sample, mfc_cfg.num_channels);
|
||||
|
||||
ret = apr_send_pkt(this_adm.apr, (uint32_t *)&mfc_cfg);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: port_id: for[0x%x] failed %d\n",
|
||||
__func__, port_id, ret);
|
||||
goto done;
|
||||
}
|
||||
/* Wait for the callback with copp id */
|
||||
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: mfc_cfg Set params timed out for port_id: for [0x%x]\n",
|
||||
__func__, port_id);
|
||||
ret = -ETIMEDOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) > 0) {
|
||||
pr_err("%s: DSP returned error[%s]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&this_adm.copp.stat
|
||||
[port_idx][copp_idx])));
|
||||
ret = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&this_adm.copp.stat
|
||||
[port_idx][copp_idx]));
|
||||
goto done;
|
||||
}
|
||||
|
||||
pr_debug("%s: mfc_cfg Set params returned success", __func__);
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(adm_swap_speaker_channels);
|
||||
|
||||
int adm_set_sound_focus(int port_id, int copp_idx,
|
||||
struct sound_focus_param soundFocusData)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue