Loading hal/audio_hw.c +24 −1 Original line number Diff line number Diff line Loading @@ -680,9 +680,15 @@ int disable_snd_device(struct audio_device *adev, if (adev->snd_dev_ref_cnt[snd_device] == 0) { audio_extn_dsm_feedback_enable(adev, snd_device, false); if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) && audio_extn_spkr_prot_is_enabled()) { audio_extn_spkr_prot_stop_processing(snd_device); // when speaker device is disabled, reset swap. // will be renabled on usecase start platform_set_swap_channels(adev, false); } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices) == 0) { Loading Loading @@ -1871,6 +1877,14 @@ int start_output_stream(struct stream_out *out) audio_extn_utils_send_app_type_gain(out->dev, out->app_type_cfg.app_type, &out->app_type_cfg.gain[0]); // consider a scenario where on pause lower layers are tear down. // so on resume, swap mixer control need to be sent only when // backend is active, hence rather than sending from enable device // sending it from start of streamtream platform_set_swap_channels(adev, true); ALOGV("%s: exit", __func__); return 0; error_open: Loading Loading @@ -2192,6 +2206,12 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) } select_devices(adev, out->usecase); audio_extn_tfa_98xx_update(); // on device switch force swap, lower functions will make sure // to check if swap is allowed or not. if (!same_dev) platform_set_swap_channels(adev, true); } } Loading Loading @@ -3904,7 +3924,10 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) status = -EINVAL; } if (status == 0) { platform_swap_lr_channels(adev, reverse_speakers); // check and set swap // - check if orientation changed and speaker active // - set rotation and cache the rotation value platform_check_and_set_swap_lr_channels(adev, reverse_speakers); } } Loading hal/msm8916/platform.c +78 −31 Original line number Diff line number Diff line Loading @@ -2258,16 +2258,70 @@ int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_u return start_gain; } int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels) { const char *mixer_ctl_name = "Swap channel"; struct mixer_ctl *ctl; const char *mixer_path; struct platform_data *my_data = (struct platform_data *)adev->platform; // forced to set to swap, but device not rotated ... ignore set if (swap_channels && !my_data->speaker_lr_swap) return 0; ALOGV("%s:", __func__); if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); return -EINVAL; } if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) { ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels); return -EINVAL; } ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ", swap_channels?"R --> L":"L --> R"); return 0; } int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; if (my_data->speaker_lr_swap != swap_channels) { my_data->speaker_lr_swap = swap_channels; return platform_set_swap_channels(adev, swap_channels); } int platform_set_swap_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; // do not swap channels in audio modes with concurrent capture and playback // as this may break the echo reference if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) { ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode); return 0; } list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && Loading @@ -2281,23 +2335,16 @@ int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) { const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1); select_devices(adev, usecase->id); if (initial_skpr_gain != -EINVAL) { if (initial_skpr_gain != -EINVAL) ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain); } } else { const char *mixer_path; if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } platform_set_swap_mixer(adev, swap_channels); } break; } } } return 0; } Loading hal/msm8960/platform.c +139 −18 Original line number Diff line number Diff line Loading @@ -1056,34 +1056,155 @@ void platform_set_echo_reference(struct audio_device *adev __unused, return; } int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) #define DEFAULT_NOMINAL_SPEAKER_GAIN 20 int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_up_gain) { // backup_gain: gain to try to set in case of an error during ramp int start_gain, end_gain, step, backup_gain, i; bool error = false; const struct mixer_ctl *ctl; const char *mixer_ctl_name_gain_left = "Left Speaker Gain"; const char *mixer_ctl_name_gain_right = "Right Speaker Gain"; struct mixer_ctl *ctl_left = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_left); struct mixer_ctl *ctl_right = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_right); if (!ctl_left || !ctl_right) { ALOGE("%s: Could not get ctl for mixer cmd - %s or %s, not applying speaker gain ramp", __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right); return -EINVAL; } else if ((mixer_ctl_get_num_values(ctl_left) != 1) || (mixer_ctl_get_num_values(ctl_right) != 1)) { ALOGE("%s: Unexpected num values for mixer cmd - %s or %s, not applying speaker gain ramp", __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right); return -EINVAL; } if (ramp_up) { start_gain = 0; end_gain = target_ramp_up_gain > 0 ? target_ramp_up_gain : DEFAULT_NOMINAL_SPEAKER_GAIN; step = +1; backup_gain = end_gain; } else { // using same gain on left and right const int left_gain = mixer_ctl_get_value(ctl_left, 0); start_gain = left_gain > 0 ? left_gain : DEFAULT_NOMINAL_SPEAKER_GAIN; end_gain = 0; step = -1; backup_gain = start_gain; } for (i = start_gain ; i != (end_gain + step) ; i += step) { //ALOGV("setting speaker gain to %d", i); if (mixer_ctl_set_value(ctl_left, 0, i)) { ALOGE("%s: error setting %s to %d during gain ramp", __func__, mixer_ctl_name_gain_left, i); error = true; break; } if (mixer_ctl_set_value(ctl_right, 0, i)) { ALOGE("%s: error setting %s to %d during gain ramp", __func__, mixer_ctl_name_gain_right, i); error = true; break; } usleep(1000); } if (error) { // an error occured during the ramp, let's still try to go back to a safe volume if (mixer_ctl_set_value(ctl_left, 0, backup_gain)) { ALOGE("%s: error restoring left gain to %d", __func__, backup_gain); } if (mixer_ctl_set_value(ctl_right, 0, backup_gain)) { ALOGE("%s: error restoring right gain to %d", __func__, backup_gain); } } return start_gain; } int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels) { const char *mixer_ctl_name = "Swap channel"; struct mixer_ctl *ctl; const char *mixer_path; struct platform_data *my_data = (struct platform_data *)adev->platform; // forced to set to swap, but device not rotated ... ignore set if (swap_channels && !my_data->speaker_lr_swap) return 0; ALOGV("%s:", __func__); if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); return -EINVAL; } if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) { ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels); return -EINVAL; } ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ", swap_channels?"R --> L":"L --> R"); return 0; } int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels) { // only update the selected device if there is active pcm playback // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; int status = 0; if (my_data->speaker_lr_swap != swap_channels) { my_data->speaker_lr_swap = swap_channels; return platform_set_swap_channels(adev, swap_channels); } int platform_set_swap_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; // do not swap channels in audio modes with concurrent capture and playback // as this may break the echo reference if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) { ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode); return 0; } list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) { const char *mixer_path; if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); /* * If acdb tuning is different for SPEAKER_REVERSE, it is must * to perform device switch to disable the current backend to * enable it with new acdb data. */ if (acdb_device_table[SND_DEVICE_OUT_SPEAKER] != acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) { const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1); select_devices(adev, usecase->id); if (initial_skpr_gain != -EINVAL) ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); platform_set_swap_mixer(adev, swap_channels); } break; } } } return status; return 0; } bool platform_send_gain_dep_cal(void *platform __unused, Loading hal/msm8974/platform.c +75 −37 Original line number Diff line number Diff line Loading @@ -167,7 +167,6 @@ static int pcm_device_table[AUDIO_USECASE_MAX][2] = { [USECASE_AUDIO_RECORD_MMAP] = {MMAP_RECORD_PCM_DEVICE, MMAP_RECORD_PCM_DEVICE}, [USECASE_AUDIO_RECORD_HIFI] = {MULTIMEDIA2_PCM_DEVICE, MULTIMEDIA2_PCM_DEVICE}, Loading Loading @@ -3172,14 +3171,62 @@ int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_u return start_gain; } int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels) { const char *mixer_ctl_name = "Swap channel"; struct mixer_ctl *ctl; const char *mixer_path; struct platform_data *my_data = (struct platform_data *)adev->platform; // forced to set to swap, but device not rotated ... ignore set if (swap_channels && !my_data->speaker_lr_swap) return 0; ALOGV("%s:", __func__); if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); return -EINVAL; } if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) { ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels); return -EINVAL; } ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ", swap_channels?"R --> L":"L --> R"); return 0; } int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; if (my_data->speaker_lr_swap != swap_channels) { my_data->speaker_lr_swap = swap_channels; return platform_set_swap_channels(adev, swap_channels); } int platform_set_swap_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; // do not swap channels in audio modes with concurrent capture and playback // as this may break the echo reference Loading @@ -3188,8 +3235,6 @@ int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) return 0; } my_data->speaker_lr_swap = swap_channels; list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && Loading @@ -3203,23 +3248,16 @@ int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) { const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1); select_devices(adev, usecase->id); if (initial_skpr_gain != -EINVAL) { if (initial_skpr_gain != -EINVAL) ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain); } } else { const char *mixer_path; if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } platform_set_swap_mixer(adev, swap_channels); } break; } } } return 0; } Loading hal/platform_api.h +2 −1 Original line number Diff line number Diff line Loading @@ -113,7 +113,8 @@ int snd_card_info_init(const char *filename, void *, set_parameters_fn); int platform_get_usecase_index(const char * usecase); int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id); void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device); int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels); int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels); int platform_set_swap_channels(struct audio_device *adev, bool swap_channels); int platform_can_split_snd_device(snd_device_t in_snd_device, int *num_devices, Loading Loading
hal/audio_hw.c +24 −1 Original line number Diff line number Diff line Loading @@ -680,9 +680,15 @@ int disable_snd_device(struct audio_device *adev, if (adev->snd_dev_ref_cnt[snd_device] == 0) { audio_extn_dsm_feedback_enable(adev, snd_device, false); if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) && audio_extn_spkr_prot_is_enabled()) { audio_extn_spkr_prot_stop_processing(snd_device); // when speaker device is disabled, reset swap. // will be renabled on usecase start platform_set_swap_channels(adev, false); } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices) == 0) { Loading Loading @@ -1871,6 +1877,14 @@ int start_output_stream(struct stream_out *out) audio_extn_utils_send_app_type_gain(out->dev, out->app_type_cfg.app_type, &out->app_type_cfg.gain[0]); // consider a scenario where on pause lower layers are tear down. // so on resume, swap mixer control need to be sent only when // backend is active, hence rather than sending from enable device // sending it from start of streamtream platform_set_swap_channels(adev, true); ALOGV("%s: exit", __func__); return 0; error_open: Loading Loading @@ -2192,6 +2206,12 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) } select_devices(adev, out->usecase); audio_extn_tfa_98xx_update(); // on device switch force swap, lower functions will make sure // to check if swap is allowed or not. if (!same_dev) platform_set_swap_channels(adev, true); } } Loading Loading @@ -3904,7 +3924,10 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) status = -EINVAL; } if (status == 0) { platform_swap_lr_channels(adev, reverse_speakers); // check and set swap // - check if orientation changed and speaker active // - set rotation and cache the rotation value platform_check_and_set_swap_lr_channels(adev, reverse_speakers); } } Loading
hal/msm8916/platform.c +78 −31 Original line number Diff line number Diff line Loading @@ -2258,16 +2258,70 @@ int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_u return start_gain; } int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels) { const char *mixer_ctl_name = "Swap channel"; struct mixer_ctl *ctl; const char *mixer_path; struct platform_data *my_data = (struct platform_data *)adev->platform; // forced to set to swap, but device not rotated ... ignore set if (swap_channels && !my_data->speaker_lr_swap) return 0; ALOGV("%s:", __func__); if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); return -EINVAL; } if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) { ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels); return -EINVAL; } ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ", swap_channels?"R --> L":"L --> R"); return 0; } int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; if (my_data->speaker_lr_swap != swap_channels) { my_data->speaker_lr_swap = swap_channels; return platform_set_swap_channels(adev, swap_channels); } int platform_set_swap_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; // do not swap channels in audio modes with concurrent capture and playback // as this may break the echo reference if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) { ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode); return 0; } list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && Loading @@ -2281,23 +2335,16 @@ int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) { const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1); select_devices(adev, usecase->id); if (initial_skpr_gain != -EINVAL) { if (initial_skpr_gain != -EINVAL) ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain); } } else { const char *mixer_path; if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } platform_set_swap_mixer(adev, swap_channels); } break; } } } return 0; } Loading
hal/msm8960/platform.c +139 −18 Original line number Diff line number Diff line Loading @@ -1056,34 +1056,155 @@ void platform_set_echo_reference(struct audio_device *adev __unused, return; } int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) #define DEFAULT_NOMINAL_SPEAKER_GAIN 20 int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_up_gain) { // backup_gain: gain to try to set in case of an error during ramp int start_gain, end_gain, step, backup_gain, i; bool error = false; const struct mixer_ctl *ctl; const char *mixer_ctl_name_gain_left = "Left Speaker Gain"; const char *mixer_ctl_name_gain_right = "Right Speaker Gain"; struct mixer_ctl *ctl_left = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_left); struct mixer_ctl *ctl_right = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name_gain_right); if (!ctl_left || !ctl_right) { ALOGE("%s: Could not get ctl for mixer cmd - %s or %s, not applying speaker gain ramp", __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right); return -EINVAL; } else if ((mixer_ctl_get_num_values(ctl_left) != 1) || (mixer_ctl_get_num_values(ctl_right) != 1)) { ALOGE("%s: Unexpected num values for mixer cmd - %s or %s, not applying speaker gain ramp", __func__, mixer_ctl_name_gain_left, mixer_ctl_name_gain_right); return -EINVAL; } if (ramp_up) { start_gain = 0; end_gain = target_ramp_up_gain > 0 ? target_ramp_up_gain : DEFAULT_NOMINAL_SPEAKER_GAIN; step = +1; backup_gain = end_gain; } else { // using same gain on left and right const int left_gain = mixer_ctl_get_value(ctl_left, 0); start_gain = left_gain > 0 ? left_gain : DEFAULT_NOMINAL_SPEAKER_GAIN; end_gain = 0; step = -1; backup_gain = start_gain; } for (i = start_gain ; i != (end_gain + step) ; i += step) { //ALOGV("setting speaker gain to %d", i); if (mixer_ctl_set_value(ctl_left, 0, i)) { ALOGE("%s: error setting %s to %d during gain ramp", __func__, mixer_ctl_name_gain_left, i); error = true; break; } if (mixer_ctl_set_value(ctl_right, 0, i)) { ALOGE("%s: error setting %s to %d during gain ramp", __func__, mixer_ctl_name_gain_right, i); error = true; break; } usleep(1000); } if (error) { // an error occured during the ramp, let's still try to go back to a safe volume if (mixer_ctl_set_value(ctl_left, 0, backup_gain)) { ALOGE("%s: error restoring left gain to %d", __func__, backup_gain); } if (mixer_ctl_set_value(ctl_right, 0, backup_gain)) { ALOGE("%s: error restoring right gain to %d", __func__, backup_gain); } } return start_gain; } int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels) { const char *mixer_ctl_name = "Swap channel"; struct mixer_ctl *ctl; const char *mixer_path; struct platform_data *my_data = (struct platform_data *)adev->platform; // forced to set to swap, but device not rotated ... ignore set if (swap_channels && !my_data->speaker_lr_swap) return 0; ALOGV("%s:", __func__); if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); return -EINVAL; } if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) { ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels); return -EINVAL; } ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ", swap_channels?"R --> L":"L --> R"); return 0; } int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels) { // only update the selected device if there is active pcm playback // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; int status = 0; if (my_data->speaker_lr_swap != swap_channels) { my_data->speaker_lr_swap = swap_channels; return platform_set_swap_channels(adev, swap_channels); } int platform_set_swap_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; // do not swap channels in audio modes with concurrent capture and playback // as this may break the echo reference if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) || (adev->mode == AUDIO_MODE_IN_CALL)) { ALOGV("%s: will not swap due to audio mode %d", __func__, adev->mode); return 0; } list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) { const char *mixer_path; if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); /* * If acdb tuning is different for SPEAKER_REVERSE, it is must * to perform device switch to disable the current backend to * enable it with new acdb data. */ if (acdb_device_table[SND_DEVICE_OUT_SPEAKER] != acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) { const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1); select_devices(adev, usecase->id); if (initial_skpr_gain != -EINVAL) ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); platform_set_swap_mixer(adev, swap_channels); } break; } } } return status; return 0; } bool platform_send_gain_dep_cal(void *platform __unused, Loading
hal/msm8974/platform.c +75 −37 Original line number Diff line number Diff line Loading @@ -167,7 +167,6 @@ static int pcm_device_table[AUDIO_USECASE_MAX][2] = { [USECASE_AUDIO_RECORD_MMAP] = {MMAP_RECORD_PCM_DEVICE, MMAP_RECORD_PCM_DEVICE}, [USECASE_AUDIO_RECORD_HIFI] = {MULTIMEDIA2_PCM_DEVICE, MULTIMEDIA2_PCM_DEVICE}, Loading Loading @@ -3172,14 +3171,62 @@ int ramp_speaker_gain(struct audio_device *adev, bool ramp_up, int target_ramp_u return start_gain; } int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) int platform_set_swap_mixer(struct audio_device *adev, bool swap_channels) { const char *mixer_ctl_name = "Swap channel"; struct mixer_ctl *ctl; const char *mixer_path; struct platform_data *my_data = (struct platform_data *)adev->platform; // forced to set to swap, but device not rotated ... ignore set if (swap_channels && !my_data->speaker_lr_swap) return 0; ALOGV("%s:", __func__); if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name); return -EINVAL; } if (mixer_ctl_set_value(ctl, 0, swap_channels) < 0) { ALOGE("%s: Could not set reverse cotrol %d",__func__, swap_channels); return -EINVAL; } ALOGV("platfor_force_swap_channel :: Channel orientation ( %s ) ", swap_channels?"R --> L":"L --> R"); return 0; } int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; if (my_data->speaker_lr_swap != swap_channels) { my_data->speaker_lr_swap = swap_channels; return platform_set_swap_channels(adev, swap_channels); } int platform_set_swap_channels(struct audio_device *adev, bool swap_channels) { // only update if there is active pcm playback on speaker struct audio_usecase *usecase; struct listnode *node; struct platform_data *my_data = (struct platform_data *)adev->platform; // do not swap channels in audio modes with concurrent capture and playback // as this may break the echo reference Loading @@ -3188,8 +3235,6 @@ int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) return 0; } my_data->speaker_lr_swap = swap_channels; list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && Loading @@ -3203,23 +3248,16 @@ int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels) acdb_device_table[SND_DEVICE_OUT_SPEAKER_REVERSE]) { const int initial_skpr_gain = ramp_speaker_gain(adev, false /*ramp_up*/, -1); select_devices(adev, usecase->id); if (initial_skpr_gain != -EINVAL) { if (initial_skpr_gain != -EINVAL) ramp_speaker_gain(adev, true /*ramp_up*/, initial_skpr_gain); } } else { const char *mixer_path; if (swap_channels) { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER_REVERSE); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } else { mixer_path = platform_get_snd_device_name(SND_DEVICE_OUT_SPEAKER); audio_route_apply_and_update_path(adev->audio_route, mixer_path); } platform_set_swap_mixer(adev, swap_channels); } break; } } } return 0; } Loading
hal/platform_api.h +2 −1 Original line number Diff line number Diff line Loading @@ -113,7 +113,8 @@ int snd_card_info_init(const char *filename, void *, set_parameters_fn); int platform_get_usecase_index(const char * usecase); int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id); void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device); int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels); int platform_check_and_set_swap_lr_channels(struct audio_device *adev, bool swap_channels); int platform_set_swap_channels(struct audio_device *adev, bool swap_channels); int platform_can_split_snd_device(snd_device_t in_snd_device, int *num_devices, Loading