/* * Copyright (C) 2017 Amlogic Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "audio_control" //#define LOG_NDEBUG 0 #include #include #include #include #include #include #include #include #include #include "audio_controls.h" #include "aml_audio_timer.h" //#include "dtv_input.h" #include "aml_malloc_debug.h" #include "aml_audio_stream.h" #include "audio_hw_ms12_v2.h" #include "audio_hw_ms12_common.h" #include "audio_hw_utils.h" #include "dolby_lib_api.h" #include "aml_alsa_mixer.h" //#include "aml_enc_api.h" #include "tv_patch_format_parser.h" #include "aml_capture_output.h" #include "audio_controls_proc.h" #define LGEParamCount 67 #define MS12_MAJOR_VERSION 2 #define MS12_MINOR_VERSION 4 //get_put_info detailed function #define OUTPUT_NUM 8 //refer to COMMON_MAX_OUTPUT #define MIX_GAIN 0 #define MAX_GAIN 0xFFFFFF struct Ioctl_update_storage proc_info_storage; static int gain_output_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = OUTPUT_NUM; uinfo->write_count = 2; uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE, uinfo->value.integer.min = MIX_GAIN; uinfo->value.integer.max = MAX_GAIN; uinfo->value.integer.step = 1; ALOGD("range(%ld->%ld)", uinfo->value.integer.min, uinfo->value.integer.max); return 0; } static int gain_output_get(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); size_t i; for (i = 1; i <= OUTPUT_NUM; i++) ucontrol->value.integer.value[i - 1] = aml_actrl->output_device_gain[i]; /* * ucontrol->value.integer.value[0] = spk_GAIN; * ucontrol->value.integer.value[1] = optic_GAIN; * ucontrol->value.integer.value[2] = optic_lg_GAIN; * ucontrol->value.integer.value[3] = bluetooth_GAIN; * ucontrol->value.integer.value[4] = hp_GAIN; * ucontrol->value.integer.value[5] = arc_GAIN; * ucontrol->value.integer.value[6] = wisa_GAIN; * ucontrol->value.integer.value[7] = se_bt_GAIN; */ return 0; } static int gain_output_put(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); int output_type = ucontrol->value.integer.value[0]; // COMMON_NO_OUTPUT to COMMON_MAX_OUTPUT int gain = ucontrol->value.integer.value[1]; int m, idx; int ret = -1, len; char env[MAX_UEVENT_LEN]; ALOGD("output type=0x%x gain=0x%x", output_type, gain); if (gain < MIX_GAIN || gain > MAX_GAIN) { ALOGE("[%s:%d] gain(%x) is over range", __func__, __LINE__, gain); return -1; } if (output_type <= COMMON_NO_OUTPUT || output_type >= COMMON_MAX_OUTPUT) { ALOGE("[%s:%d] output_type(%x) is over range", __func__, __LINE__, output_type); return -1; } // it's mask bits as output_type for (m = 1, idx = 0; m < COMMON_MAX_OUTPUT; m = m << 1, idx++) { if (output_type & m) { ALOGD("output idx=%d", idx); aml_actrl->output_device_gain[idx] = gain; break; } } proc_info_storage.output_gain_array_s[output_type] =gain; audio_proc_ioctl_update(OUTPUT_GAIN_ARRAY_E, &proc_info_storage); memset(env, 0, sizeof(env)); len = snprintf(env, MAX_UEVENT_LEN, "GAIN_OUTPUT=%d %d", ++idx, gain); control_utils(env); ALOGD("env=%s len=%d ret=%d\n", env, len, ret); return 0; } #define ADEC_PORT 4 #define MIXER_PORT 8 static int gain_input_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE, uinfo->element_count = 24; // array size when get uinfo->write_count = 3; uinfo->value.integer.min = MIX_GAIN; uinfo->value.integer.max = MAX_GAIN; ALOGD("range(%ld->%ld) ", uinfo->value.integer.min, uinfo->value.integer.max); return 0; } static int gain_input_get(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); int i; for (i = 0; i < ADEC_PORT; i+=2) { ucontrol->value.integer.value[i] = i/2; ucontrol->value.integer.value[i + 1] = aml_actrl->adec_gain[i/2]; } for (i = 0; i < MIXER_PORT; i+=2) { ALOGI("the mixer port is %d, the num is %f", i/2, aml_actrl->amixer_gain[i/2].target_gain); ucontrol->value.integer.value[i + 2*ADEC_PORT] = i/2; ucontrol->value.integer.value[i + 2*ADEC_PORT + 1] = aml_actrl->amixer_gain[i/2].target_gain; } return 0; } //The range of gain is 0~0xFFFFFF static int gain_input_put(struct aml_ahal_ctl_elem_value *ucontrol) { int input_type = ucontrol->value.integer.value[0]; // common_input_ext_type_t int input_port_num = ucontrol->value.integer.value[1]; int gain = ucontrol->value.integer.value[2]; int duration = 0; int ret = -1, len; char env[MAX_UEVENT_LEN]; if (gain < MIX_GAIN || gain > MAX_GAIN) { ALOGE("[%s:%d] gain(%x) is over range", __func__, __LINE__, gain); return -1; } ALOGD("type=%d port=%d gain=%d ", input_type, input_port_num, gain); if (input_type == INPUT_ADEC) { proc_info_storage.adec_gain_array_s[input_port_num] =gain; audio_proc_ioctl_update(ADEC_GAIN_ARRAY_E, &proc_info_storage); } memset(env, 0, sizeof(env)); len = snprintf(env, MAX_UEVENT_LEN, "GAIN_INPUT=%d %d %d %d", input_type, input_port_num, gain, duration); control_utils(env); ALOGD("env=%s len=%d ret=%d\n", env, len, ret); return 0; } // this is for GAIN_INPUT_DURATION static int adec_duration_array[ADEC_NUM]; static int amixer_duration_array[AMIXER_NUM]; static int gain_input_duration_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE, uinfo->write_count = 4; uinfo->element_count = 3 * (ADEC_NUM + AMIXER_NUM); // array size when get uinfo->value.integer.min = 0; uinfo->value.integer.max = 0xffffff; return 0; } static int gain_input_duration_info_get(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); ucontrol->value.integer.value[0] = 0; // := 0 ucontrol->value.integer.value[1] = aml_actrl->adec_gain[0]; // why skip 2? follow customer's definition ucontrol->value.integer.value[2] = adec_duration_array[0]; ucontrol->value.integer.value[3] = 1; // := 1 ucontrol->value.integer.value[4] = aml_actrl->adec_gain[1]; ucontrol->value.integer.value[5] = adec_duration_array[1]; ucontrol->value.integer.value[6] = 2; // := 2 ucontrol->value.integer.value[7] = aml_actrl->adec_gain[2]; ucontrol->value.integer.value[8] = adec_duration_array[2]; ucontrol->value.integer.value[9] = 3; // := 3 ucontrol->value.integer.value[10] = aml_actrl->adec_gain[3]; ucontrol->value.integer.value[11] = adec_duration_array[3]; ucontrol->value.integer.value[12] = 0; // := 0 ucontrol->value.integer.value[13] = aml_actrl->amixer_gain[0].target_gain; ucontrol->value.integer.value[14] = amixer_duration_array[0]; ucontrol->value.integer.value[15] = 1; // := 1 ucontrol->value.integer.value[16] = aml_actrl->amixer_gain[1].target_gain; ucontrol->value.integer.value[17] = amixer_duration_array[1]; ucontrol->value.integer.value[18] = 2; // := 2 ucontrol->value.integer.value[19] = aml_actrl->amixer_gain[2].target_gain; ucontrol->value.integer.value[20] = amixer_duration_array[2]; ucontrol->value.integer.value[21] = 3; // := 3 ucontrol->value.integer.value[22] = aml_actrl->amixer_gain[3].target_gain; ucontrol->value.integer.value[23] = amixer_duration_array[3]; ucontrol->value.integer.value[24] = 4; // := 4 ucontrol->value.integer.value[25] = aml_actrl->amixer_gain[4].target_gain; ucontrol->value.integer.value[26] = amixer_duration_array[4]; ucontrol->value.integer.value[27] = 5; // := 5 ucontrol->value.integer.value[28] = aml_actrl->amixer_gain[5].target_gain; ucontrol->value.integer.value[29] = amixer_duration_array[5]; ucontrol->value.integer.value[30] = 6; // := 6 ucontrol->value.integer.value[31] = aml_actrl->amixer_gain[6].target_gain; ucontrol->value.integer.value[32] = amixer_duration_array[6]; ucontrol->value.integer.value[33] = 7; // := 7 ucontrol->value.integer.value[34] = aml_actrl->amixer_gain[7].target_gain; ucontrol->value.integer.value[35] = amixer_duration_array[7]; return 0; } static int gain_input_duration_info_put(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); int input_type = ucontrol->value.integer.value[0]; int input_port_num = ucontrol->value.integer.value[1]; int gain = ucontrol->value.integer.value[2]; int duration = ucontrol->value.integer.value[3]; ALOGD("type=%d port=%d gain=%d duration=%d", input_type, input_port_num, gain, duration); if (input_type == COMMON_INPUT_ADEC && input_port_num < ADEC_NUM) { aml_actrl->adec_gain[input_port_num] = gain; adec_duration_array[input_port_num] = duration; } else if (input_type == COMMON_INPUT_AMIXER && input_port_num < AMIXER_NUM) { aml_actrl->amixer_gain[input_port_num].target_gain = gain; amixer_duration_array[input_port_num] = duration; } else { ALOGE("unknown type=%d input_port_num=%d", input_type, input_port_num); } return 0; } int sound_engine_volume; static int Sound_Engine_Lite_Volume_Param_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->write_count = 1; uinfo->element_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 100; ALOGD("range(%ld->%ld)", uinfo->value.integer.min, uinfo->value.integer.max); return 0; } static int Sound_Engine_Lite_Volume_Param_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = sound_engine_volume; return 0; } static int Sound_Engine_Lite_Volume_Param_put(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); int gain = ucontrol->value.integer.value[0]; int ret = -1, len; char env[MAX_UEVENT_LEN]; ALOGD("Sound_Engine_Lite_Volume =%d", gain); if (gain < MIX_GAIN || gain > 100) { ALOGE("[%s:%d] gain(%d) is over range", __func__, __LINE__, gain); return -1; } sound_engine_volume = gain + aml_actrl->output_device_gain[0] * 100 / 0x00800000; memset(env, 0, sizeof(env)); len = snprintf(env, MAX_UEVENT_LEN, "lgse_var_fn009=%d", sound_engine_volume); control_utils(env); ALOGD("env=%s len=%d ret=%d\n", env, len, ret); return 0; } static int mute_input_info (struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2 * (ADEC_NUM + AMIXER_NUM); uinfo->write_count = ADEC_NUM + AMIXER_NUM; return 0; } static int mute_input_get (struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); ucontrol->value.integer.value[0] = 0; // := 0 ucontrol->value.integer.value[1] = aml_actrl->adec_mute[0]; ucontrol->value.integer.value[2] = 1; // := 1 ucontrol->value.integer.value[3] = aml_actrl->adec_mute[1]; ucontrol->value.integer.value[4] = 2; // := 2 ucontrol->value.integer.value[5] = aml_actrl->adec_mute[2]; ucontrol->value.integer.value[6] = 3; // := 3 ucontrol->value.integer.value[7] = aml_actrl->adec_mute[3]; ucontrol->value.integer.value[8] = 0; // := 0 ucontrol->value.integer.value[9] = aml_actrl->amixer_mute[0]; ucontrol->value.integer.value[10] = 1; // := 1 ucontrol->value.integer.value[11] = aml_actrl->amixer_mute[1]; ucontrol->value.integer.value[12] = 2; // := 2 ucontrol->value.integer.value[13] = aml_actrl->amixer_mute[2]; ucontrol->value.integer.value[14] = 3; // := 3 ucontrol->value.integer.value[15] = aml_actrl->amixer_mute[3]; ucontrol->value.integer.value[16] = 4; // := 4 ucontrol->value.integer.value[17] = aml_actrl->amixer_mute[4]; ucontrol->value.integer.value[18] = 5; // := 5 ucontrol->value.integer.value[19] = aml_actrl->amixer_mute[5]; ucontrol->value.integer.value[20] = 6; // := 6 ucontrol->value.integer.value[21] = aml_actrl->amixer_mute[6]; ucontrol->value.integer.value[22] = 7; // := 7 ucontrol->value.integer.value[23] = aml_actrl->amixer_mute[7]; return 0; } static int mute_input_put(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); int input_type = ucontrol->value.integer.value[0]; int input_port_num = ucontrol->value.integer.value[1]; int mute_status = ucontrol->value.integer.value[2]; int ret = -1, len; char env[MAX_UEVENT_LEN]; ALOGD("type=%d port=%d mute=%d", input_type, input_port_num, mute_status); if (mute_status < 0 || mute_status > 1) { ALOGE("[%s:%d] mute_status(%x) is over range", __func__, __LINE__, mute_status); return -1; } if (input_type == COMMON_INPUT_ADEC) { if (input_port_num >= 0 && input_port_num < ADEC_NUM) { aml_actrl->adec_mute[input_port_num] = mute_status; proc_info_storage.adec_mute_array_s[input_port_num] =mute_status; audio_proc_ioctl_update(ADEC_MUTE_ARRAY_E, &proc_info_storage); } else { ALOGE("[%s:%d] COMMON_INPUT_ADEC in_num(%d) is over range", __func__, __LINE__, input_port_num); return -1; } } else if (input_type == COMMON_INPUT_AMIXER) { if (input_port_num >= 0 && input_port_num < AMIXER_NUM) { aml_actrl->amixer_mute[input_port_num] = mute_status; } else { ALOGE("[%s:%d] COMMON_INPUT_AMIXER innum(%d) is over range", __func__, __LINE__, input_port_num); return -1; } } else { ALOGE("[%s:%d] unknown type=%d input_port_num=%d", __func__, __LINE__, input_type, input_port_num); return -1; } memset(env, 0, sizeof(env)); len = snprintf(env, MAX_UEVENT_LEN, "MUTE_INPUT=%d %d %d", input_type, input_port_num, mute_status); control_utils(env); ALOGD("env=%s len=%d ret=%d\n", env, len, ret); return 0; } //SET_OUTPUT_MUTE static int mute_output_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = OUTPUT_NUM + 1; // one more capture_mute uinfo->write_count = 2; return 0; } static int mute_output_get(struct aml_ahal_ctl_elem_value *ucontrol) { size_t i; aml_audio_control *aml_actrl = get_audio_control(); for (i = 0; i != OUTPUT_NUM + 1; i++) ucontrol->value.integer.value[i] = aml_actrl->output_device_mute[i]; return 0; } static int mute_output_put(struct aml_ahal_ctl_elem_value *ucontrol) { aml_audio_control *aml_actrl = get_audio_control(); int output_type = ucontrol->value.integer.value[0]; int mute_status = ucontrol->value.integer.value[1]; int m, i; int ret = -1, len; char env[MAX_UEVENT_LEN]; ALOGD("output type=0x%x mute=0x%x", output_type, mute_status); if (mute_status < 0 || mute_status > 1) { ALOGE("[%s:%d] mute_status(%x) is over range", __func__, __LINE__, mute_status); return -1; } if (output_type <= COMMON_NO_OUTPUT || output_type >= COMMON_MAX_OUTPUT) { ALOGE("[%s:%d] output_type(%x) is over range", __func__, __LINE__, output_type); return -1; } for (m = 1, i = 0; m < COMMON_MAX_OUTPUT; m = m << 1, i++) { if (output_type & m) { aml_actrl->output_device_mute[i] = mute_status; break; } } proc_info_storage.output_mute_array_s[i] = aml_actrl->output_device_mute[i]; audio_proc_ioctl_update(OUTPUT_MUTE_ARRAY_E, &proc_info_storage); memset(env, 0, sizeof(env)); len = snprintf(env, MAX_UEVENT_LEN, "MUTE_OUTPUT=%d %d", i, mute_status); control_utils(env); ALOGD("env=%s len=%d ret=%d\n", env, len, ret); return 0; } int adec_delay_array[ADEC_NUM]; int amixer_delay_array[AMIXER_NUM]; int output_delay_array[OUTPUT_NUM + 1]; static int ad_gain; #define MIN_DELAY 0 #define INPUT_MAX_DELAY 250 #define OUTPUT_MAX_DELAY 400 static int delay_inputoutput_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 33; uinfo->write_count = 5; return 0; } static int delay_inputoutput_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; // := 0 ucontrol->value.integer.value[1] = adec_delay_array[0]; ucontrol->value.integer.value[2] = 1; // := 1 ucontrol->value.integer.value[3] = adec_delay_array[1]; ucontrol->value.integer.value[4] = 2; // := 2 ucontrol->value.integer.value[5] = adec_delay_array[2]; ucontrol->value.integer.value[6] = 3; // := 3 ucontrol->value.integer.value[7] = adec_delay_array[3]; ucontrol->value.integer.value[8] = 0; // := 0 ucontrol->value.integer.value[9] = amixer_delay_array[0]; ucontrol->value.integer.value[10] = 1; // := 1 ucontrol->value.integer.value[11] = amixer_delay_array[1]; ucontrol->value.integer.value[12] = 2; // := 2 ucontrol->value.integer.value[13] = amixer_delay_array[2]; ucontrol->value.integer.value[14] = 3; // := 3 ucontrol->value.integer.value[15] = amixer_delay_array[3]; ucontrol->value.integer.value[16] = 4; // := 4 ucontrol->value.integer.value[17] = amixer_delay_array[4]; ucontrol->value.integer.value[18] = 5; // := 5 ucontrol->value.integer.value[19] = amixer_delay_array[5]; ucontrol->value.integer.value[20] = 6; // := 6 ucontrol->value.integer.value[21] = amixer_delay_array[6]; ucontrol->value.integer.value[22] = 7; // := 7 ucontrol->value.integer.value[23] = amixer_delay_array[7]; ucontrol->value.integer.value[24] = output_delay_array[0]; // spk_delay; ucontrol->value.integer.value[25] = output_delay_array[1]; // optic_delay; ucontrol->value.integer.value[26] = output_delay_array[2]; // optic_lg_delay; ucontrol->value.integer.value[27] = output_delay_array[3]; // bluetooth_delay; ucontrol->value.integer.value[28] = output_delay_array[4]; // hp_delay; ucontrol->value.integer.value[29] = output_delay_array[5]; // arc_delay; ucontrol->value.integer.value[30] = output_delay_array[6]; // wisa_delay; ucontrol->value.integer.value[31] = output_delay_array[7]; // sebt_delay; ucontrol->value.integer.value[32] = output_delay_array[8]; // capture_delay; return 0; } static int delay_inputoutput_put(struct aml_ahal_ctl_elem_value *ucontrol) { int input_type, input_port_num, input_delay, output_type, output_delay; int m; int i = 0; int ret = -1, len; char env[MAX_UEVENT_LEN]; input_type = ucontrol->value.integer.value[0]; input_port_num = ucontrol->value.integer.value[1]; input_delay = ucontrol->value.integer.value[2]; output_type = ucontrol->value.integer.value[3]; output_delay = ucontrol->value.integer.value[4]; ALOGD("%d %d %d %d %d\n", input_type, input_port_num, input_delay, output_type, output_delay); if (input_delay < MIN_DELAY || input_delay > INPUT_MAX_DELAY) { ALOGE("[%s:%d] input_delay(%x) is over range", __func__, __LINE__, input_delay); return -1; } if (output_delay < MIN_DELAY || output_delay > OUTPUT_MAX_DELAY) { ALOGE("[%s:%d] output_delay(%x) is over range", __func__, __LINE__, output_delay); return -1; } if (input_type == COMMON_INPUT_ADEC) { if (input_port_num >= 0 && input_port_num < ADEC_NUM) { adec_delay_array[input_port_num] = input_delay; proc_info_storage.adec_delay_array_s[input_port_num] =adec_delay_array[input_port_num]; audio_proc_ioctl_update(ADEC_DELAY_ARRAY_E, &proc_info_storage); } else { ALOGE("[%s:%d] COMMON_INPUT_ADEC innum(%d) is over range", __func__, __LINE__, input_port_num); return -1; } } else if (input_type == COMMON_INPUT_AMIXER) { if (input_port_num >= 0 && input_port_num < AMIXER_NUM) { amixer_delay_array[input_port_num] = input_delay; proc_info_storage.amixer_delay_array_s[input_port_num] =amixer_delay_array[input_port_num]; audio_proc_ioctl_update(AMIXER_DELAY_ARRAY_E, &proc_info_storage); } else { ALOGE("[%s:%d] COMMON_INPUT_AMIXER in_num(%d) is over range", __func__, __LINE__, input_port_num); return -1; } } else { ALOGE("[%s:%d] unknown type=%d input_port_num=%d", __func__, __LINE__, input_type, input_port_num); } if (output_type > COMMON_NO_OUTPUT && output_type <= COMMON_MAX_OUTPUT) { for (m = 1, i = 0; m <= COMMON_MAX_OUTPUT; m = m << 1, i++) { if (output_type & m) { output_delay_array[i] = output_delay; proc_info_storage.output_delay_array_s[i] = output_delay_array[i]; audio_proc_ioctl_update(OUTPUT_DELAY_ARRAY_E, &proc_info_storage); break; } } } memset(env, 0, sizeof(env)); len = snprintf(env, MAX_UEVENT_LEN, "DELAY_INPUTOUTPUT=%d %d %d %d %d", input_type, input_port_num, input_delay, i, output_delay); control_utils(env); ALOGD("env=%s len=%d ret=%d\n", env, len, ret); return 0; } //audio_latency struct latency_param param_letency; static int audio_latency_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 5; return 0; } static int audio_latency_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = param_letency.in_param.input_type; ucontrol->value.integer.value[1] = param_letency.in_param.port_number; ucontrol->value.integer.value[2] = param_letency.in_param.input_source; ucontrol->value.integer.value[3] = param_letency.output_type; ucontrol->value.integer.value[4] = 0; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0; ucontrol->value.integer.value[7] = param_letency.latency_time; return 0; } static int audio_latency_put(struct aml_ahal_ctl_elem_value *ucontrol) { int input_type = ucontrol->value.integer.value[0]; int port_number = ucontrol->value.integer.value[1]; int input_source = ucontrol->value.integer.value[2]; int output_type = ucontrol->value.integer.value[3]; int latency_time = ucontrol->value.integer.value[4]; ALOGD("%d, %d, %d, %d, %d", input_type, port_number, input_source, output_type, latency_time); if (((input_type == INPUT_ADEC && port_number < ADEC_NUM) || (input_type == INPUT_AMIXER && port_number < AMIXER_NUM)) && (input_source >= INPUT_SOURCE_ATV && input_source <= INPUT_SOURCE_HDMI) && output_type > OUTPUT_DEVICE_UNKNOWN) { param_letency.in_param.input_type = ucontrol->value.integer.value[0]; param_letency.in_param.port_number = ucontrol->value.integer.value[1]; param_letency.in_param.input_source = ucontrol->value.integer.value[2]; param_letency.output_type = ucontrol->value.integer.value[3]; param_letency.latency_time = ucontrol->value.integer.value[4]; return 0; } return -1; } static int audio_low_latency_mode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 24; uinfo->write_count = 3; return 0; } static int audio_low_latency_mode_get(struct aml_ahal_ctl_elem_value *ucontrol) { // get low latency mode for each input ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[4] = 2; ucontrol->value.integer.value[5] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[6] = 3; ucontrol->value.integer.value[7] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[8] = 0; ucontrol->value.integer.value[9] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[10] = 1; ucontrol->value.integer.value[11] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[12] = 2; ucontrol->value.integer.value[13] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[14] = 3; ucontrol->value.integer.value[15] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[16] = 4; ucontrol->value.integer.value[17] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[18] = 5; ucontrol->value.integer.value[19] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[20] = 6; ucontrol->value.integer.value[21] = param_letency.in_param.low_latency_mode; ucontrol->value.integer.value[22] = 7; ucontrol->value.integer.value[23] = param_letency.in_param.low_latency_mode; return 0; } static int audio_low_latency_mode_put(struct aml_ahal_ctl_elem_value *ucontrol) { common_input_ext_type_t input_type = ucontrol->value.integer.value[0]; int input_port_num = ucontrol->value.integer.value[1]; low_latency_mode_type_t low_latency_mode = ucontrol->value.integer.value[2]; ALOGD("%d, %d, %d", input_type, input_port_num, low_latency_mode); if ((input_type == COMMON_INPUT_ADEC || input_type == COMMON_INPUT_AMIXER) && (low_latency_mode >= LOW_LATENCY_MODE_OFF && low_latency_mode <= LOW_LATENCY_MODE_BYPASS_FADER)) { param_letency.in_param.input_type = input_type; param_letency.in_param.port_number = input_port_num; param_letency.in_param.low_latency_mode = low_latency_mode; return 0; } return -1; } static int gain_audiodescription_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; uinfo->value.integer.min = MIX_GAIN; uinfo->value.integer.max = MAX_GAIN; ALOGD("range(%ld->%ld)", uinfo->value.integer.min, uinfo->value.integer.max); return 0; } static int gain_audiodescription_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = ad_gain; return 0; } static int gain_audiodescription_put(struct aml_ahal_ctl_elem_value *ucontrol) { int gain = ucontrol->value.integer.value[0]; int ret = -1, len; char env[MAX_UEVENT_LEN]; if (gain < MIX_GAIN || gain > MAX_GAIN) { ALOGE("[%s:%d] gain(%x) is over range", __func__, __LINE__, gain); return -1; } ad_gain = gain; memset(env, 0, sizeof(env)); len = snprintf(env, MAX_UEVENT_LEN, "GAIN_AUDIODESCRIPTION=%d", ad_gain); control_utils(env); ALOGD("env=%s len=%d ret=%d", env, len, ret); return 0; } static int adc_open_status; static int adc_close_status; static int connected_hw_port = DEFAULT_ADC_HW_PORT; static int adc_disconnect_status; static int adc_open_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int adc_open_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = adc_open_status; return 0; } static int adc_open_put(struct aml_ahal_ctl_elem_value *ucontrol) { if (!adc_open_status) { adc_open_status = ucontrol->value.integer.value[0]; adc_close_status = 0; return 0; } return -1; } static int adc_close_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int adc_close_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = adc_close_status; return 0; } static int adc_close_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int ret = 0; if (adc_open_status) { adc_close_status = ucontrol->value.integer.value[0]; adc_open_status = 0; if (connected_hw_port != 0xff) { connected_hw_port = 0xff; //if we call "Adc Close", this value should be default. // for the case "Adc Open"->"Adc Connect"->"Adc Close", //not call "Adc Disconnect", when call "Adc Close", //we should inform audio hal to disconnect ADC memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADC_DISCONNECT"); control_utils(env); } return ret; } return -1; } static int adc_connect_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int adc_connect_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = connected_hw_port; return 0; } static int adc_connect_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int ret = 0; if (adc_open_status && connected_hw_port == 0xff) { // connect must after open connected_hw_port = ucontrol->value.integer.value[0]; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADC_CONNECT"); control_utils(env); return ret; } return -1; } static int adc_disconnect_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int adc_disconnect_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = adc_disconnect_status; return 0; } static int adc_disconnect_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int ret = 0; if (adc_open_status && connected_hw_port != 0xff) { adc_disconnect_status = ucontrol->value.integer.value[0]; connected_hw_port = 0xff; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADC_DISCONNECT"); control_utils(env); return ret; } return -1; } static int adec_open_status[ADEC_MAX_CAP]; static int adec_close_status[ADEC_MAX_CAP]; static int adec_connect_port[ADEC_MAX_CAP]; static int adec_pre_connect_port[ADEC_MAX_CAP]; static int adec_disconnect_status[ADEC_MAX_CAP]; static int adec_start_status[ADEC_MAX_CAP]; static int adec_stop_status[ADEC_MAX_CAP]; static int adec_codec_status[ADEC_MAX_CAP]; static void clear_adec_status(int adec_index) { adec_disconnect_status[adec_index] = 0; adec_stop_status[adec_index] = 0; adec_start_status[adec_index] = 0; adec_codec_status[adec_index] = 0; proc_info_storage.adec_start_status_s[adec_index] = adec_start_status[adec_index]; audio_proc_ioctl_update(ADEC_START_STATUS_E, &proc_info_storage); proc_info_storage.adec_codec_status_s[adec_index] = adec_codec_status[adec_index]; audio_proc_ioctl_update(ADEC_CODEC_STATUS_E, &proc_info_storage); } //ADEC_OPEN static int adec_open_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 2; uinfo->value.integer.step = 1; return 0; } static int adec_open_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_open_status[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_open_status[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_open_put(struct aml_ahal_ctl_elem_value *ucontrol) { int adec_index = ucontrol->value.integer.value[0]; ALOGD("adec_index=%d", adec_index); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] == 0) { adec_open_status[adec_index] = 1; adec_close_status[adec_index] = 0; proc_info_storage.adec_open_status_s[adec_index] = adec_open_status[adec_index]; audio_proc_ioctl_update(ADEC_OPEN_STATUS_E, &proc_info_storage); return 0; } return -1; } //ADEC_CLOSE static int adec_close_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 2; uinfo->value.integer.step = 1; return 0; } static int adec_close_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_close_status[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_close_status[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_close_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; ALOGD("adec_index=%d\n", adec_index); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] == 1 /* && !adec_connect_port[adec_index]*/) { adec_open_status[adec_index] = 0; adec_close_status[adec_index] = 1; proc_info_storage.adec_open_status_s[adec_index] = adec_open_status[adec_index]; audio_proc_ioctl_update(ADEC_OPEN_STATUS_E, &proc_info_storage); if (adec_connect_port[adec_index] != 0) { adec_pre_connect_port[adec_index] = adec_connect_port[adec_index]; adec_connect_port[adec_index] = 0; proc_info_storage.adec_connect_port_s[adec_index] = adec_connect_port[adec_index]; audio_proc_ioctl_update(ADEC_CONNECT_PORT_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_DISCONNECT=%d", adec_index); //LGSE flow may adec_open->adec_connect->adec_close. //There is no adec_disconnect,so we need send disconnect event here control_utils(env); } clear_adec_status(adec_index); return 0; } return -1; } //ADEC_CONNECT static int adec_connect_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 256; uinfo->value.integer.step = 1; return 0; } static int adec_connect_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_connect_port[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_connect_port[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_connect_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; //adec_src_port_index_ext_type int src_port_index = ucontrol->value.integer.value[1]; ALOGD("adec_index=%d src_port_index=%d\n", adec_index, src_port_index); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] == 0) { adec_connect_port[adec_index] = src_port_index; proc_info_storage.adec_connect_port_s[adec_index] = adec_connect_port[adec_index]; audio_proc_ioctl_update(ADEC_CONNECT_PORT_E, &proc_info_storage); adec_disconnect_status[adec_index] = 0; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_CONNECT=%d %d", adec_index, src_port_index); control_utils(env); return 0; } return -1; } //ADEC_DISCONNECT static int adec_disconnect_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 256; uinfo->value.integer.step = 1; return 0; } static int adec_disconnect_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_disconnect_status[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_disconnect_status[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_disconnect_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; ALOGD("adec_index=%d\n", adec_index); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_connect_port[adec_index]) { adec_pre_connect_port[adec_index] = adec_connect_port[adec_index]; adec_connect_port[adec_index] = 0; proc_info_storage.adec_connect_port_s[adec_index] = adec_connect_port[adec_index]; audio_proc_ioctl_update(ADEC_OPEN_STATUS_E, &proc_info_storage); adec_disconnect_status[adec_index] = 1; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_DISCONNECT=%d", adec_index); control_utils(env); return 0; } return -1; } //downmix_mode void control_utils(char *msg); int adec_downmix_mode[ADEC_MAX_CAP]; #define MAX_UEVENT_LEN 128 static int adec_downmix_mode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 25; uinfo->value.integer.step = 1; return 0; } static int adec_downmix_mode_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_downmix_mode[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_downmix_mode[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_downmix_mode_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; //adec_downmix_mode_ext_type_tDownMixMode int downmix_mode = ucontrol->value.integer.value[1]; ALOGD("adec=%d downmix_mode=%d", adec_index, downmix_mode); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && downmix_mode >= ADEC_LORO_MODE && downmix_mode <= ADEC_LTRT_MODE) { adec_downmix_mode[adec_index] = downmix_mode; proc_info_storage.adec_downmix_mode_s[adec_index] = adec_downmix_mode[adec_index]; audio_proc_ioctl_update(ADEC_DOWNMIX_MODE_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_DOWNMIXMODE=%d %d", adec_index, downmix_mode); ALOGD("down_mixmode %s", env); control_utils(env); return 0; } return -1; } int cur_codec[ADEC_MAX_CAP];// to do : ADEC0_INFO int src_codec[ADEC_MAX_CAP];// to do : ADEC0_INFO static int adec_codec_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 256; uinfo->value.integer.step = 1; return 0; } static int adec_codec_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_codec_status[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_codec_status[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_codec_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; //adec_src_codec_ext_type_t int codec_type = ucontrol->value.integer.value[1]; ALOGD("adec: %d codec: %d\n", adec_index, codec_type); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index]) { adec_codec_status[adec_index] = codec_type; // when will clear it? proc_info_storage.adec_codec_status_s[adec_index] = adec_codec_status[adec_index]; audio_proc_ioctl_update(ADEC_CODEC_STATUS_E, &proc_info_storage); cur_codec[adec_index] = codec_type; src_codec[adec_index] = codec_type; proc_info_storage.cur_codec_s[adec_index] = cur_codec[adec_index]; proc_info_storage.src_codec_s[adec_index] = src_codec[adec_index]; audio_proc_ioctl_update(CUR_CODEC_E, &proc_info_storage); audio_proc_ioctl_update(SRC_CODEC_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_CODEC=%d %d", adec_index, codec_type); control_utils(env); return 0; } return -1; } static int adec_start_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 2; uinfo->value.integer.step = 1; return 0; } static int adec_start_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_start_status[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_start_status[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_start_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; ALOGD("adec_index=%d\n", adec_index); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index] && !adec_start_status[adec_index]) { adec_start_status[adec_index] = 1; proc_info_storage.adec_start_status_s[adec_index] = adec_start_status[adec_index]; audio_proc_ioctl_update(ADEC_START_STATUS_E, &proc_info_storage); adec_stop_status[adec_index] = 0; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_START=%d", adec_index); control_utils(env); return 0; } return -1; } static int adec_stop_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 2; uinfo->value.integer.step = 1; return 0; } static int adec_stop_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_stop_status[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_stop_status[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_stop_put(struct aml_ahal_ctl_elem_value *ucontrol) // how to start or stop decoder in audio hal????? { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; ALOGD("adec_index=%d\n", adec_index); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_start_status[adec_index]) { adec_start_status[adec_index] = 0; proc_info_storage.adec_start_status_s[adec_index] = adec_start_status[adec_index]; audio_proc_ioctl_update(ADEC_START_STATUS_E, &proc_info_storage); adec_stop_status[adec_index] = 1; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_STOP=%d", adec_index); control_utils(env); return 0; } return -1; } static int adec_maxcapacity_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count = 0; return 0; } static int adec_maxcapacity_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = ADEC_MAX_CAP; ucontrol->value.integer.value[1] = AMIXER_NUM; return 0; } static int adec_maxcapacity_put(struct aml_ahal_ctl_elem_value *ucontrol) // how to start or stop decoder in audio hal????? { return 0; } static int user_adec_max_cap; static int user_amixer_max_cap; static int adec_usermaxcapacity_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count = 2; return 0; } static int adec_usermaxcapacity_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = user_adec_max_cap; ucontrol->value.integer.value[1] = user_amixer_max_cap; return 0; } static int adec_usermaxcapacity_put(struct aml_ahal_ctl_elem_value *ucontrol) // how to start or stop decoder in audio hal????? { int adec_max_cap = ucontrol->value.integer.value[0]; int amixer_max_cap = ucontrol->value.integer.value[1]; ALOGD("adec_max=%d amixer_max=%d\n", adec_max_cap, amixer_max_cap); if (adec_max_cap >= 0 && adec_max_cap <= ADEC_MAX_CAP && amixer_max_cap >= 0 && amixer_max_cap <= AMIXER_NUM) { user_adec_max_cap = adec_max_cap; user_amixer_max_cap = amixer_max_cap; return 0; } return -1; } int adec_output_mode[ADEC_MAX_CAP]; static int adec_decoder_outputmode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_decoder_outputmode_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_output_mode[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_output_mode[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_decoder_outputmode_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; //adec_dualmono_mode_t int dual_mono_mode = ucontrol->value.integer.value[1]; ALOGD("adec=%d dual_mono=%d", adec_index, dual_mono_mode); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index]) { adec_output_mode[adec_index] = dual_mono_mode; proc_info_storage.adec_output_mode_s[adec_index] = adec_output_mode[adec_index]; audio_proc_ioctl_update(ADEC_OUTPUT_MODE_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_TP_DECODER_OUTPUTMODE=%d %d", adec_index, dual_mono_mode); control_utils(env); return 0; } return -1; } int adec_sync_mode[ADEC_MAX_CAP]; static int adec_syncmode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_syncmode_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_sync_mode[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_sync_mode[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_syncmode_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; //adec_dualmono_mode_t int sync_onoff = ucontrol->value.integer.value[1]; ALOGD("adec=%d sync_onoff=%d", adec_index, sync_onoff); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && sync_onoff >= 0 && sync_onoff <= 1) { adec_sync_mode[adec_index] = sync_onoff; proc_info_storage.adec_sync_mode_s[adec_index] = adec_sync_mode[adec_index]; audio_proc_ioctl_update(ADEC_SYNC_MODE_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_SYNCMODE=%d %d", adec_index, sync_onoff); control_utils(env); return 0; } return -1; } int adec_dolyb_drc_mode[ADEC_MAX_CAP]; static int adec_dolby_drcmode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_dolby_drcmode_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_dolyb_drc_mode[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_dolyb_drc_mode[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_dolby_drcmode_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int drc_mode = ucontrol->value.integer.value[1];//adec_dolbydrc_mode_ext_type_t ALOGD("adec=%d drc_mode=%d", adec_index, drc_mode); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && drc_mode >= ADEC_DOLBY_LINE_MODE && drc_mode <= ADEC_DOLBY_DRC_OFF) { adec_dolyb_drc_mode[adec_index] = drc_mode; proc_info_storage.adec_dolyb_drc_mode_s[adec_index] = adec_dolyb_drc_mode[adec_index]; audio_proc_ioctl_update(ADEC_DOLYB_DRC_MODE_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_DOLBYDRCMODE=%d %d", adec_index, drc_mode); control_utils(env); return 0; } return -1; } int adec_pts[ADEC_MAX_CAP]; static struct buffer_status adec_tp_buffer_status[ADEC_MAX_CAP]; int adec_info_get_main(int adec_index, struct aml_ahal_ctl_elem_value *ucontrol, int info_type) { if (adec_open_status[adec_index]) { switch (info_type) { case ADEC_INFO_TYPE_INFO: ucontrol->value.integer.value[0] = adec_index;//adec_port_number; ucontrol->value.integer.value[1] = adec_start_status[adec_index]; ucontrol->value.integer.value[2] = adec_codec_status[adec_index]; // codecSet //curAdecFormat; // codecDecoded // to do ucontrol->value.integer.value[3] = cur_codec[adec_index]; //sourceAdecFormat; // codecSrc // to do ucontrol->value.integer.value[4] = src_codec[adec_index]; ucontrol->value.integer.value[5] = adec_connect_port[adec_index]; ucontrol->value.integer.value[6] = 0;//prevAdecInputPort; // to do //curAdecDualMonoMode; ucontrol->value.integer.value[7] = adec_output_mode[adec_index]; ucontrol->value.integer.value[8] = 0;//IsEsExist; // to do ucontrol->value.integer.value[9] = 0;//audioMode; // to do ucontrol->value.integer.value[10] = 0;//heaac_version; // to do //heaac_trasmissionformat; // to do ucontrol->value.integer.value[11] = 0; ucontrol->value.integer.value[12] = 0;//heeac_channelNum; // to do ucontrol->value.integer.value[13] = 0;//mpeg_bitrate; // to do ucontrol->value.integer.value[14] = 0;//mpeg_sampleRate; // to do ucontrol->value.integer.value[15] = 0;//mpeg_layer; // to do ucontrol->value.integer.value[16] = 0;//mpeg_channelNum; // to do ucontrol->value.integer.value[17] = 0;//ac3_bitrate; // to do ucontrol->value.integer.value[18] = 0;//ac3_sampleRate; // to do ucontrol->value.integer.value[19] = 0;//ac3_channelnum; // to do ucontrol->value.integer.value[20] = 0;//ac3_EAC3; // to do return 0; case ADEC_INFO_TYPE_TP_BUFFER: ucontrol->value.integer.value[0] = adec_tp_buffer_status[adec_index].max_size; ucontrol->value.integer.value[1] = adec_tp_buffer_status[adec_index].free_size; return 0; case ADEC_INFO_TYPE_TP_PTS: ucontrol->value.integer.value[0] = adec_pts[adec_index]; return 0; default: return -1; } } return -1; } static int adec0_info_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 21; uinfo->write_count = 0; return 0; } static int adec0_info_get(struct aml_ahal_ctl_elem_value *ucontrol) { return adec_info_get_main(0, ucontrol, ADEC_INFO_TYPE_INFO); } static int adec0_info_put(struct aml_ahal_ctl_elem_value *ucontrol) // how to start or stop decoder in audio hal????? { //to do return 0; } static int adec1_info_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 21; uinfo->write_count = 0; return 0; } static int adec1_info_get(struct aml_ahal_ctl_elem_value *ucontrol) { return adec_info_get_main(1, ucontrol, ADEC_INFO_TYPE_INFO); } static int adec1_info_put(struct aml_ahal_ctl_elem_value *ucontrol) // how to start or stop decoder in audio hal????? { //to do return 0; } int adec_default_prl[ADEC_MAX_CAP]; static int adec_default_prl_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_default_prl_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_default_prl[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_default_prl[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_default_prl_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int default_prl = ucontrol->value.integer.value[1]; ALOGD("adec=%d default_prl=%d", adec_index, default_prl); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && default_prl != 100) { //to do: default_prl != 100 only to pass socts, I do not know the range of prl adec_default_prl[adec_index] = default_prl; proc_info_storage.adec_default_prl_s[adec_index] =adec_default_prl[adec_index]; audio_proc_ioctl_update(ADEC_DEFAULT_PRL_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_DEFAULTPRL=%d %d", adec_index, default_prl); control_utils(env); return 0; } return -1; } int adec_trick_mode[ADEC_MAX_CAP]; static int adec_trick_mode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_trick_mode_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_trick_mode[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_trick_mode[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_trick_mode_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; //adec_trick_mode_ext_type_t int trick_mode = ucontrol->value.integer.value[1]; ALOGD("adec=%d trick_mode=%d", adec_index, trick_mode); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && trick_mode >= ADEC_TRICK_NONE && trick_mode <= ADEC_TRICK_FAST_FORWARD_2P00X) { adec_trick_mode[adec_index] = trick_mode; proc_info_storage.adec_trick_mode_s[adec_index] = adec_trick_mode[adec_index]; audio_proc_ioctl_update(ADEC_TRICK_MODE_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_TRICKMODE=%d %d", adec_index, trick_mode); control_utils(env); return 0; } return -1; } static struct ad_status tp_ad_status; int adec_ad_onoff[ADEC_MAX_CAP]; static int adec_audiodescription_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_audiodescription_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = tp_ad_status.adec_idex; ucontrol->value.integer.value[1] = tp_ad_status.ad_onoff; return 0; } static int adec_audiodescription_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int ad_onoff = ucontrol->value.integer.value[1]; //true of false ALOGD("adec_index=%d ad_onoff=%d", adec_index, ad_onoff); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[0] && adec_open_status[1]) { // reference https://harmony.lge.com:8443/issue/browse/AMLREQ-104 adec_ad_onoff[adec_index] = ad_onoff; proc_info_storage.adec_ad_onoff_s[adec_index] =adec_ad_onoff[adec_index]; audio_proc_ioctl_update(ADEC_AD_ONOFF_E, &proc_info_storage); tp_ad_status.adec_idex = adec_index; tp_ad_status.ad_onoff = ad_onoff; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_TP_AUDIODESCRIPTION=%d %d", adec_index, ad_onoff); control_utils(env); return 0; } return -1; } static int adec0_tp_pts_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 0; return 0; } static int adec0_tp_pts_get(struct aml_ahal_ctl_elem_value *ucontrol) { return adec_info_get_main(0, ucontrol, ADEC_INFO_TYPE_TP_PTS); } static int adec0_tp_pts_put(struct aml_ahal_ctl_elem_value *ucontrol) // how to start or stop decoder in audio hal????? { //to do : set adec_pts[0] return 0; } static int adec1_tp_pts_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 0; return 0; } static int adec1_tp_pts_get(struct aml_ahal_ctl_elem_value *ucontrol) { return adec_info_get_main(1, ucontrol, ADEC_INFO_TYPE_TP_PTS); } static int adec1_tp_pts_put(struct aml_ahal_ctl_elem_value *ucontrol) // how to start or stop decoder in audio hal????? { //to do : set adec_pts[1] return 0; } static int adec_ac4_firstlang_type[ADEC_MAX_CAP]; static int adec_firstlang[ADEC_MAX_CAP]; static int adec_ac4_secondlang_type[ADEC_MAX_CAP]; static int adec_secondlang[ADEC_MAX_CAP]; static int adec_ac4_auto1stlang_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 12; uinfo->write_count = 3; return 0; } static int adec_ac4_auto1stlang_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_firstlang_type[0]; ucontrol->value.integer.value[2] = adec_firstlang[0]; ucontrol->value.integer.value[3] = 1; ucontrol->value.integer.value[4] = adec_ac4_firstlang_type[1]; ucontrol->value.integer.value[5] = adec_firstlang[1]; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; ucontrol->value.integer.value[8] = 0; ucontrol->value.integer.value[9] = 0xFFFF; ucontrol->value.integer.value[10] = 0; ucontrol->value.integer.value[11] = 0; return 0; } static int adec_ac4_auto1stlang_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int lang_type = ucontrol->value.integer.value[1];//adec_ac4_lang_code_ext_type_t int first_lang = ucontrol->value.integer.value[2]; ALOGD("adec_index=%d lang_type=%d first_lang=%x", adec_index, lang_type, first_lang); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index]) { adec_ac4_firstlang_type[adec_index] = lang_type; adec_firstlang[adec_index] = first_lang; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_AUTO1STLANG=%d %d %d", adec_index, lang_type, first_lang); control_utils(env); return 0; } return -1; } static int adec_ac4_auto2ndlang_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 12; uinfo->write_count = 3; return 0; } static int adec_ac4_auto2ndlang_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_secondlang_type[0]; ucontrol->value.integer.value[2] = adec_secondlang[0]; ucontrol->value.integer.value[3] = 1; ucontrol->value.integer.value[4] = adec_ac4_secondlang_type[0]; ucontrol->value.integer.value[5] = adec_secondlang[1]; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; ucontrol->value.integer.value[8] = 0; ucontrol->value.integer.value[9] = 0xFFFF; ucontrol->value.integer.value[10] = 0; ucontrol->value.integer.value[11] = 0; return 0; } static int adec_ac4_auto2ndlang_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int lang_type = ucontrol->value.integer.value[1];//adec_ac4_lang_code_ext_type_t int second_lang = ucontrol->value.integer.value[2]; ALOGD("adec=%d lang_type=%d second_lang=%x", adec_index, lang_type, second_lang); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index]) { adec_ac4_secondlang_type[adec_index] = lang_type; adec_secondlang[adec_index] = second_lang; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_AUTO2NDLANG=%d %d %d", adec_index, lang_type, second_lang); control_utils(env); return 0; } return -1; } static int adec_ac4_ad_type[ADEC_MAX_CAP]; static int adec_ac4_prioritize_ad_type[ADEC_MAX_CAP]; static int adec_ac4_dialogenhance_gain[ADEC_MAX_CAP]; static int adec_ac4_admixing[ADEC_MAX_CAP]; static int adec_ac4_pres_group_idx[ADEC_MAX_CAP]; static int adec_ac4_ad_type_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_ac4_ad_type_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_ad_type[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_ac4_ad_type[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_ac4_ad_type_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int ad_type = ucontrol->value.integer.value[1];//adec_ac4_ad_ext_type_t ALOGD("adec_index=%d ad_type=%d", adec_index, ad_type); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index]) { adec_ac4_ad_type[adec_index] = ad_type; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_AUTO_ADTYPE=%d %d", adec_index, ad_type); control_utils(env); return 0; } return -1; } static int adec_ac4_prioritize_ad_type_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_ac4_prioritize_ad_type_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_prioritize_ad_type[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_ac4_prioritize_ad_type[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_ac4_prioritize_ad_type_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int ad_type = ucontrol->value.integer.value[1];//true or flase ALOGD("adec_index=%d ad_type=%d", adec_index, ad_type); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index]) { adec_ac4_prioritize_ad_type[adec_index] = ad_type; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_AUTO_PRIORITIZE_ADTYPE=%d %d", adec_index, ad_type); control_utils(env); return 0; } return -1; } static int adec_ac4_dialogenhance_gain_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_ac4_dialogenhance_gain_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_dialogenhance_gain[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_ac4_dialogenhance_gain[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_ac4_dialogenhance_gain_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int ac4_dialogenhance_gain = ucontrol->value.integer.value[1];//true or flase ALOGD("adec=%d ac4_de_gain=%d", adec_index, ac4_dialogenhance_gain); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index]) { adec_ac4_dialogenhance_gain[adec_index] = ac4_dialogenhance_gain; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_AUTO_PRIORITIZE_ADTYPE=%d %d", adec_index, ac4_dialogenhance_gain); control_utils(env); return 0; } return -1; } static int adec_ac4_admixing_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_ac4_admixing_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_admixing[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_ac4_admixing[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_ac4_admixing_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int ac4_admixing = ucontrol->value.integer.value[1];//true or flase ALOGD("adec=%d ac4_admixing=%d", adec_index, ac4_admixing); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index] && adec_ac4_ad_type[adec_index] != ADEC_AC4_AD_TYPE_NONE) { adec_ac4_admixing[adec_index] = ac4_admixing; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_AUTO_ADMIXING=%d %d", adec_index, ac4_admixing); control_utils(env); return 0; } return -1; } static int adec_ac4_pres_group_idx_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_ac4_pres_group_idx_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_pres_group_idx[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_ac4_pres_group_idx[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_ac4_pres_group_idx_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int ac4_pres_group_idx = ucontrol->value.integer.value[1]; ALOGD("adec=%d ac4_pres_group_idx=%d\n", adec_index, ac4_pres_group_idx); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && adec_open_status[adec_index] && adec_connect_port[adec_index] && adec_codec_status[adec_index] && ac4_pres_group_idx >= 0 && ac4_pres_group_idx <= 0x20) { adec_ac4_pres_group_idx[adec_index] = ac4_pres_group_idx; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_PRES_GROUP_IDX=%d %d", adec_index, ac4_pres_group_idx); control_utils(env); return 0; } return -1; } static int ott_mode; static int atmos_lock; int open_sndout; static int close_sndout; static int adec_ac4_associate_volume[ADEC_MAX_CAP]; int adec_lipsync_offset[ADEC_MAX_CAP]; int adec_master_syncmode[ADEC_MAX_CAP]; int connect_sndout_status[9]; static int disconnect_sndout_status[3]; static int connect_sndout_pos[4]; static int adec_dolby_ottmode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count = 2; return 0; } static int adec_dolby_ottmode_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = ott_mode; ucontrol->value.integer.value[1] = atmos_lock; return 0; } static int adec_dolby_ottmode_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int ott_mod = ucontrol->value.integer.value[0]; int atmos_locking = ucontrol->value.integer.value[1]; ALOGD("ott_mod=%d atmos_locking=%d", ott_mod, atmos_locking); if (ott_mod == 0 && atmos_locking == 1) { //call with bIsOTTEnable=FALSE and bIsATMOSLockingEnable=TRUE, //the API should return FALSE without any action. return -1; } ott_mode = ott_mod; atmos_lock = atmos_locking; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_DOLBY_OTTMODE=%d %d", ott_mod, atmos_locking); control_utils(env); return 0; } static int adec0_tp_bufferstatus_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count = 0; return 0; } static int adec0_tp_bufferstatus_get(struct aml_ahal_ctl_elem_value *ucontrol) { return adec_info_get_main(0, ucontrol, ADEC_INFO_TYPE_TP_BUFFER); } static int adec0_tp_bufferstatus_put(struct aml_ahal_ctl_elem_value *ucontrol) { //to do : set adec_tp_buffer_status[0] return 0; } static int adec1_tp_bufferstatus_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count = 0; return 0; } static int adec1_tp_bufferstatus_get(struct aml_ahal_ctl_elem_value *ucontrol) { return adec_info_get_main(1, ucontrol, ADEC_INFO_TYPE_TP_BUFFER); } static int adec1_tp_bufferstatus_put(struct aml_ahal_ctl_elem_value *ucontrol) { //to do : set adec_tp_buffer_status[11] return 0; } static int adec_ac4_associate_volume_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_ac4_associate_volume_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_ac4_associate_volume[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_ac4_associate_volume[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_ac4_associate_volume_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int ac4_associate_volume = ucontrol->value.integer.value[1]; ALOGD("adec_index=%d ac4_associate_volume=%d", adec_index, ac4_associate_volume); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP && ac4_associate_volume >= AC4_ADVOLUME_MIN && ac4_associate_volume <= AC4_ADVOLUME_MAX /* && adec_open_status[adec_index] && adec_connect_port[adec_index]*/) { adec_ac4_associate_volume[adec_index] = ac4_associate_volume; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_AC4_ASSOCIATE_AUDIO_VOLUME=%d %d", adec_index, ac4_associate_volume); control_utils(env); return 0; } return -1; } static int adec_lipsync_offset_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_lipsync_offset_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_lipsync_offset[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_lipsync_offset[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_lipsync_offset_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int offset_time = ucontrol->value.integer.value[1]; ALOGD("adec_index=%d offset_time=%d", adec_index, offset_time); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP) { adec_lipsync_offset[adec_index] = offset_time; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_LIPSYNC_OFFSET=%d %d", adec_index, offset_time); control_utils(env); return 0; } return -1; } static int adec_master_syncmode_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 8; uinfo->write_count = 2; return 0; } static int adec_master_syncmode_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0; ucontrol->value.integer.value[1] = adec_master_syncmode[0]; ucontrol->value.integer.value[2] = 1; ucontrol->value.integer.value[3] = adec_master_syncmode[1]; ucontrol->value.integer.value[4] = 0xFFFF; ucontrol->value.integer.value[5] = 0; ucontrol->value.integer.value[6] = 0xFFFF; ucontrol->value.integer.value[7] = 0; return 0; } static int adec_master_syncmode_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int adec_index = ucontrol->value.integer.value[0]; int sync_onoff = ucontrol->value.integer.value[1]; ALOGD("adec_index=%d sync_onoff=%d", adec_index, sync_onoff); if (adec_index >= 0 && adec_index < ADEC_MAX_CAP) { adec_master_syncmode[adec_index] = sync_onoff; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "ADEC_MASTER_SYNCMODE=%d %d", adec_index, sync_onoff); control_utils(env); return 0; } return -1; } static int sndout_open_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_open_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = open_sndout; return 0; } static int sndout_open_put(struct aml_ahal_ctl_elem_value *ucontrol) { int open_device = ucontrol->value.integer.value[0]; ALOGD("open_device=%d", open_device); if ((open_sndout & open_device) == 0 && open_device >= 0) { open_sndout |= open_device; proc_info_storage.open_sndout_s =open_sndout; audio_proc_ioctl_update(OPEN_SNDOUT_E, &proc_info_storage); return 0; } return -1; } static int sndout_close_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_close_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = close_sndout; return 0; } static int sndout_close_put(struct aml_ahal_ctl_elem_value *ucontrol) { int device = ucontrol->value.integer.value[0]; int i = 0, j = 0; ALOGD("device=%d", device); if (device < 0) return -1; if (open_sndout & device) { close_sndout = device; open_sndout &= ~close_sndout; proc_info_storage.open_sndout_s =open_sndout; audio_proc_ioctl_update(OPEN_SNDOUT_E, &proc_info_storage); //when close, clear connect for (i = 0; i < 4; i++) { if (connect_sndout_pos[i] == device) { if (1) { // clear connect status connect_sndout_status[2 * i + 1] = 0; connect_sndout_status[2 * i + 1 + 1] = 0; //move forward two position for (j = 2 * i + 1; j <= 5;) { connect_sndout_status[j] = connect_sndout_status[j + 2]; connect_sndout_status[j + 1] = connect_sndout_status[j + 1 + 2]; j += 2; } connect_sndout_status[7] = 0; connect_sndout_status[8] = 0; //clear connect_sndout_pos connect_sndout_pos[i] = 0; for (j = i; j <= 2; j++) connect_sndout_pos[j] = connect_sndout_pos[j + 1]; connect_sndout_pos[3] = 0; break; } } } for (i = 0; i < 4; i++) { if (connect_sndout_pos[i] == device) break; } if (i == 4) { // output is not connected to input connect_sndout_status[0] &= ~device; } memcpy(proc_info_storage.connect_sndout_status_s, connect_sndout_status, sizeof(connect_sndout_status)); audio_proc_ioctl_update(CONNECT_SNDOUT_STATUS_E, &proc_info_storage); return 0; } return -1; } static int sndout_connect_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 9; uinfo->write_count = 3; return 0; } static int sndout_connect_get(struct aml_ahal_ctl_elem_value *ucontrol) { int i = 0; for (i = 0; i < 9; i++) ucontrol->value.integer.value[i] = connect_sndout_status[i]; return 0; } static int sndout_connect_put(struct aml_ahal_ctl_elem_value *ucontrol) { int output = ucontrol->value.integer.value[0];//common_output_ext_type_t int input = ucontrol->value.integer.value[1];//common_input_ext_type_t int input_port_number = ucontrol->value.integer.value[2]; int i = 0; char env[MAX_UEVENT_LEN]; ALOGD("output=%d input=%d input_port_number=%d", output, input, input_port_number); // open should before connect if ((open_sndout & output) == 0 || input_port_number >= 4) return -1; //check whether already connect before if (connect_sndout_status[0] & output) { for (i = 0; i < 4; i++) { if (connect_sndout_pos[i] == output) { if (connect_sndout_status[2 * i + 1] == input && connect_sndout_status[2 * i + 2] == input_port_number) { return -1; // already connect } } } } connect_sndout_status[0] |= output; // from index 1, move back two position for (i = 8; i >= 4;) { connect_sndout_status[i] = connect_sndout_status[i - 2]; connect_sndout_status[i - 1] = connect_sndout_status[i - 1 - 2]; i -= 2; } connect_sndout_status[1] = input; connect_sndout_status[2] = input_port_number; // from index 1, move back 1 position for (i = 3; i >= 1; i--) connect_sndout_pos[i] = connect_sndout_pos[i - 1]; connect_sndout_pos[0] = output; memcpy(proc_info_storage.connect_sndout_status_s, connect_sndout_status, sizeof(connect_sndout_status)); audio_proc_ioctl_update(CONNECT_SNDOUT_STATUS_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_CONNECT=%d %d %d", output, input, input_port_number); control_utils(env); return 0; } static int sndout_disconnect_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 3; uinfo->write_count = 3; return 0; } static int sndout_disconnect_get(struct aml_ahal_ctl_elem_value *ucontrol) { int i = 0; for (i = 0; i < 3; i++) ucontrol->value.integer.value[i] = disconnect_sndout_status[i]; return 0; } static int sndout_disconnect_put(struct aml_ahal_ctl_elem_value *ucontrol) { int output = ucontrol->value.integer.value[0]; int input = ucontrol->value.integer.value[1]; int input_port_number = ucontrol->value.integer.value[2]; int i = 0; int j = 0; char env[MAX_UEVENT_LEN]; ALOGD("output=%d input=%d input_port_number=%d", output, input, input_port_number); if (input_port_number >= 4) return -1; disconnect_sndout_status[0] = output; disconnect_sndout_status[1] = input; disconnect_sndout_status[2] = input_port_number; for (i = 0; i < 4; i++) { if (connect_sndout_pos[i] == output) { if (connect_sndout_status[2 * i + 1] == input && connect_sndout_status[2 * i + 1 + 1] == input_port_number) { // clear connect status connect_sndout_status[2 * i + 1] = 0; connect_sndout_status[2 * i + 1 + 1] = 0; //move forward two position for (j = 2 * i + 1; j <= 5;) { connect_sndout_status[j] = connect_sndout_status[j + 2]; connect_sndout_status[j + 1] = connect_sndout_status[j + 1 + 2]; j += 2; } connect_sndout_status[7] = 0; connect_sndout_status[8] = 0; //clear connect_sndout_pos connect_sndout_pos[i] = 0; for (j = i; j <= 2; j++) connect_sndout_pos[j] = connect_sndout_pos[j + 1]; connect_sndout_pos[3] = 0; break; } } } for (i = 0; i < 4; i++) { if (connect_sndout_pos[i] == output) break; } if (i == 4) { // output is not connected to input connect_sndout_status[0] &= ~output; } memcpy(proc_info_storage.connect_sndout_status_s, connect_sndout_status, sizeof(connect_sndout_status)); audio_proc_ioctl_update(CONNECT_SNDOUT_STATUS_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_DISCONNECT=%d %d %d", output, input, input_port_number); control_utils(env); return 0; } struct input_param main_audio; int optic_output_type; // sndout_optic_mode_ext_type_t int arc_output_type; // sndout_arc_mode_ext_type_t int optic_cp_info; int arc_cp_info; //static int optic_category_code; //static int arc_category_code; int optic_light_onoff; int arc_onoff; static int sndout_mainaudio_output_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count =2; return 0; } static int sndout_mainaudio_output_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = main_audio.input_type; ucontrol->value.integer.value[1] = main_audio.port_number; return 0; } static int sndout_mainaudio_output_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int input_type = ucontrol->value.integer.value[0]; int port_number = ucontrol->value.integer.value[1]; ALOGD("input_type=%d port_number=%d", input_type, port_number); if ((input_type == COMMON_INPUT_ADEC && port_number >= 0 && port_number < ADEC_MAX_CAP) || (input_type == COMMON_INPUT_AMIXER && port_number >= 0 && port_number < AMIXER_NUM)) { main_audio.input_type = input_type; main_audio.port_number = port_number; memcpy(&proc_info_storage.main_audio_s, &main_audio, sizeof(main_audio)); audio_proc_ioctl_update(MAIN_AUDIO_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_MAINAUDIO_OUTPUT=%d %d", input_type, port_number); control_utils(env); return 0; } return -1; } static int sndout_spdif_output_type_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count =2; return 0; } static int sndout_spdif_output_type_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = optic_output_type; ucontrol->value.integer.value[1] = arc_output_type; return 0; } static int sndout_spdif_output_type_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int optic_type = ucontrol->value.integer.value[0];// sndout_optic_mode_ext_type_t int arc_type = ucontrol->value.integer.value[1];// sndout_arc_mode_ext_type_t ALOGD("optic_type=%d arc_type=%d\n", optic_type, arc_type); if (optic_type >= SNDOUT_OPTIC_NONE && optic_type <= SNDOUT_OPTIC_BYPASS_AAC && arc_type >= SNDOUT_ARC_NONE && arc_type <= SNDOUT_ARC_BYPASS_EAC3_MPEG4_AAC) { optic_output_type = optic_type; proc_info_storage.optic_output_type_s = optic_output_type; audio_proc_ioctl_update(OPTIC_OUTPUT_TYPE_E, &proc_info_storage); arc_output_type = arc_type; proc_info_storage.arc_output_type_s = arc_output_type; audio_proc_ioctl_update(ARC_OUTPUT_TYPE_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_SPDIF_OUTPUTTYPE=%d %d", optic_type, arc_type); control_utils(env); return 0; } return -1; } #if 0 static int sndout_spdif_cp_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count =2; uinfo->value.integer.min = SNDOUT_OPTIC_COPY_UNKNOWN; uinfo->value.integer.max = SNDOUT_ARC_COPY_NEVER; return 0; } static int sndout_spdif_cp_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = optic_cp_info; ucontrol->value.integer.value[1] = arc_cp_info; return 0; } #define CP_BIT (1 << 2) #define L_BIT (1 << 15) extern int aml_earctx_set_audio_cs_category_code(int category_code); extern int aml_earctx_get_audio_cs_category_code(int *category_code); extern int aml_earctx_set_audio_cs_cp(int cp); extern int spdif_get_channel_status0(int spdif_id); extern void spdif_set_channel_status0(int spdif_id, unsigned int status0); static int sndout_spdif_cp_put(struct aml_ahal_ctl_elem_value *ucontrol) { //char env[MAX_UEVENT_LEN]; int optic_cp = ucontrol->value.integer.value[0];//sndout_optic_copyprotection_ext_type_t int arc_cp = ucontrol->value.integer.value[1];//sndout_arc_copyprotection_ext_type_t int spdif_id = 0;//we assume LGE use spdif_a. if not, change this value unsigned int status0 = 0; unsigned int last_status0 = 0; int arc_category_code = 0; ALOGD("optic_cp=%d arc_cp=%d", optic_cp, arc_cp); if (optic_cp >= SNDOUT_OPTIC_COPY_UNKNOWN && optic_cp <= SNDOUT_OPTIC_COPY_NEVER && arc_cp >= SNDOUT_ARC_COPY_UNKNOWN && arc_cp <= SNDOUT_ARC_COPY_NEVER) { optic_cp_info = optic_cp; arc_cp_info = arc_cp; //memset(env, 0, sizeof(env)); //snprintf(env, MAX_UEVENT_LEN, "SNDOUT_SPDIF_COPYPROTECTIONINFO=%d %d", //optic_cp, arc_cp); //kctrl_send_uevent(env); //set spdif cp status0 = spdif_get_channel_status0(spdif_id); last_status0 = status0; if (optic_cp == SNDOUT_OPTIC_COPY_FREE) {/**< cp-bit : 1, L-bit : 0 */ status0 |= CP_BIT; status0 &= ~(L_BIT); } else if (optic_cp == SNDOUT_OPTIC_COPY_NO_MORE || optic_cp == SNDOUT_OPTIC_COPY_NEVER) {/**< cp-bit : 0, L-bit : 1 */ status0 |= L_BIT; status0 &= ~(CP_BIT); } else if (optic_cp == SNDOUT_OPTIC_COPY_ONCE) {/**< cp-bit : 0, L-bit : 0 */ status0 &= ~(CP_BIT); status0 &= ~(L_BIT); } ALOGD("spdif_id=%d last_status0=0x%x status0=0x%x", spdif_id, last_status0, status0); spdif_set_channel_status0(spdif_id, status0); //set arc cp aml_earctx_get_audio_cs_category_code(&arc_category_code);//8 bit if (arc_cp == SNDOUT_OPTIC_COPY_FREE) {/**< cp-bit : 1, L-bit : 0 */ aml_earctx_set_audio_cs_cp(1); arc_category_code &= ~(L_BIT >> 8); } else if (arc_cp == SNDOUT_OPTIC_COPY_NO_MORE || optic_cp == SNDOUT_OPTIC_COPY_NEVER) {/**< cp-bit : 0, L-bit : 1 */ aml_earctx_set_audio_cs_cp(0); arc_category_code |= (L_BIT >> 8); } else if (arc_cp == SNDOUT_OPTIC_COPY_ONCE) {/**< cp-bit : 0, L-bit : 0 */ aml_earctx_set_audio_cs_cp(0); arc_category_code &= ~(L_BIT >> 8); } ALOGD("arc_category_code=0x%x", arc_category_code); aml_earctx_set_audio_cs_category_code(arc_category_code); return 0; } return -1; } static int sndout_category_code_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count =2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 0xff; return 0; } static int sndout_category_code_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = optic_category_code; ucontrol->value.integer.value[1] = arc_category_code; return 0; } static int sndout_category_code_put(struct aml_ahal_ctl_elem_value *ucontrol) { //char env[MAX_UEVENT_LEN]; int optic_category = ucontrol->value.integer.value[0]; int arc_category = ucontrol->value.integer.value[1]; int spdif_id = 0;//we assume LGE use spdif_a. if not, change this value unsigned int status0 = 0; unsigned int last_status0 = 0; ALOGD("optic_category=%d arc_category=%d", optic_category, arc_category); if (optic_category >= 0 && arc_category >= 0) { optic_category_code = optic_category; arc_category_code = arc_category; //memset(env, 0, sizeof(env)); //snprintf(env, MAX_UEVENT_LEN, "SNDOUT_SPDIF_CATERGORYCODE=%d %d", //optic_category, arc_category); //kctrl_send_uevent(env); //set optic category code status0 = spdif_get_channel_status0(spdif_id); last_status0 = status0; //clear category code low 7 bit in channels stats bit8~bit14 status0 &= ~(0x7f << 8); //set category code low 7 bit in channels stats bit8~bit14 status0 |= ((optic_category & 0x7f) << 8); ALOGD("spdif_id=%d last_status0=0x%x status0=0x%x", spdif_id, last_status0, status0); spdif_set_channel_status0(spdif_id, status0); //set arc category code aml_earctx_get_audio_cs_category_code(&arc_category_code);//8 bit //clear category code low 7 bit arc_category_code &= ~(0x7f); //set category code low 7 bit arc_category_code |= (optic_category & 0x7f); ALOGD("arc_category_code=0x%x", arc_category_code); aml_earctx_set_audio_cs_category_code(arc_category_code); return 0; } return -1; } #endif static int sndout_optic_light_onoff_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_optic_light_onoff_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = optic_light_onoff; return 0; } static int sndout_optic_light_onoff_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int light_onoff = ucontrol->value.integer.value[0]; ALOGD("light_onoff=%d", light_onoff); if (light_onoff == 0 || light_onoff == 1) { optic_light_onoff = light_onoff; proc_info_storage.optic_light_onoff_s = optic_light_onoff; audio_proc_ioctl_update(OPTIC_LIGHT_ONOFF_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_OPTIC_LIGHTONOFF=%d", light_onoff); control_utils(env); return 0; } return -1; } #if 0 static int sndout_arc_onoff_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0; } static int sndout_arc_onoff_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = arc_onoff; return 0; } extern int set_arc_earc_enable(int on_off); static int sndout_arc_onoff_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int onoff = ucontrol->value.integer.value[0]; ALOGD("onoff=%d", onoff); if (onoff == 0 || onoff == 1) { arc_onoff = onoff; if (set_arc_earc_enable(onoff) == 0) { memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_ARC_ONOFF=%d", onoff); control_utils(env); } return 0; } return -1; } #endif int spk_output_type; static int capture_disable; static int capture_output_sample_reate; int earc_onoff; struct output_type earc_output; static struct output_type optic_output; static struct output_type arc_output; static int eac3_atmos_encode_onoff; static int capture_path; struct optic_lg_param optic_lg_status; static int sndout_optic_lg_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 5; uinfo->write_count = 4; return 0; } static int sndout_optic_lg_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = optic_lg_status.bar_id; ucontrol->value.integer.value[1] = optic_lg_status.volume; ucontrol->value.integer.value[2] = optic_lg_status.mute_on_off; ucontrol->value.integer.value[3] = optic_lg_status.power_on_off; ucontrol->value.integer.value[4] = optic_lg_status.checksum; return 0; } static int sndout_optic_lg_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int bar_id = ucontrol->value.integer.value[0]; int volume = ucontrol->value.integer.value[1]; int mute_on_off = ucontrol->value.integer.value[2]; int power_on_off = ucontrol->value.integer.value[3]; ALOGD("bar_id=%d volume=%d mute_on_off=%d power_on_off=%d\n", bar_id, volume, mute_on_off, power_on_off); if (volume >= 0 && volume <= 100 && (mute_on_off == 0 || mute_on_off == 1) && (power_on_off == 0 || power_on_off == 1) && (open_sndout & COMMON_OPTIC_LG)) { optic_lg_status.bar_id = bar_id; optic_lg_status.volume = volume; optic_lg_status.mute_on_off = mute_on_off; optic_lg_status.power_on_off = power_on_off; memcpy(&proc_info_storage.optic_lg_status_s, &optic_lg_status, sizeof(optic_lg_status)); audio_proc_ioctl_update(OPTIC_LG_STATUS_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_OPTIC_LG=%d %d %d %d", bar_id, volume, mute_on_off, power_on_off); control_utils(env); return 0; } return -1; } static int sndout_spk_output_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_spk_output_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = spk_output_type; return 0; } static int sndout_spk_output_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int output_type = ucontrol->value.integer.value[0]; int channel = 0; ALOGD("output_type=%d", output_type); if (output_type >= SNDOUT_SPK_OUTPUT_UNKNOWN && output_type <= SNDOUT_SPK_OUTPUT_4CHANNEL) { spk_output_type = output_type; proc_info_storage.spk_output_type_s =spk_output_type; audio_proc_ioctl_update(SPK_OUTPUT_TYPE_E, &proc_info_storage); memset(env, 0, sizeof(env)); if (output_type == SNDOUT_SPK_OUTPUT_2CHANNEL) channel = 2; else if (output_type == SNDOUT_SPK_OUTPUT_4CHANNEL) channel = 4; snprintf(env, MAX_UEVENT_LEN, "SNDOUT_SPK_OUTPUT=%d", channel); control_utils(env); return 0; } return -1; } static int sndout_capture_disable_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_capture_disable_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = capture_disable; return 0; } static int sndout_capture_disable_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int capture_disable_onoff = ucontrol->value.integer.value[0]; ALOGD("capture_disable_onoff=%d\n", capture_disable_onoff); if (capture_disable_onoff == 0 || capture_disable_onoff == 1) { capture_disable = capture_disable_onoff; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_CAPTURE_DISABLE=%d", capture_disable_onoff); control_utils(env); return 0; } return -1; } static int sndout_capture_input_clock_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 2; uinfo->write_count = 1; return 0; } static int sndout_capture_input_clock_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = 0;//clock_count; ucontrol->value.integer.value[1] = 0;//90000; return 0; } static int sndout_capture_input_clock_put(struct aml_ahal_ctl_elem_value *ucontrol) { //to do return 0; } static int sndout_capture_output_resampling_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_capture_output_resampling_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = capture_output_sample_reate; return 0; } static int sndout_capture_output_resampling_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int sample_rate = ucontrol->value.integer.value[0]; ALOGD("sample_rate=%d\n", sample_rate); if (sample_rate > 0) { capture_output_sample_reate = sample_rate; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_CAPTURE_OUTPUT_RESAMPLING=%d", sample_rate); control_utils(env); return 0; } return -1; } #if 0 static int sndout_earc_onoff_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0; } static int sndout_earc_onoff_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = earc_onoff; return 0; } static int sndout_earc_onoff_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int on_off = ucontrol->value.integer.value[0]; ALOGD("on_off=%d\n", on_off); if (on_off == 0 || on_off == 1) { earc_onoff = on_off; if (set_arc_earc_enable(on_off) == 0) { memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_EARC_ONOFF=%d", on_off); control_utils(env); } return 0; } return -1; } #endif static int sndout_earc_output_type_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 5; uinfo->write_count = 5; return 0; } static int sndout_earc_output_type_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = earc_output.set_type; ucontrol->value.integer.value[1] = earc_output.codec_type; ucontrol->value.integer.value[2] = earc_output.channel_num; ucontrol->value.integer.value[3] = earc_output.sample_rate; ucontrol->value.integer.value[4] = earc_output.mix_option; return 0; } static int sndout_earc_output_type_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int set_type = ucontrol->value.integer.value[0]; int codec_type = ucontrol->value.integer.value[1]; int channel_num = ucontrol->value.integer.value[2]; int sample_rate = ucontrol->value.integer.value[3]; int mix_option = ucontrol->value.integer.value[4]; ALOGD("set_type=%d codec_type=%d channel_num=%d sample_rate=%d mix_option=%d\n", set_type, codec_type, channel_num, sample_rate, mix_option); if (set_type >= SNDOUT_EARC_OUTPUT_SET_NONE && set_type <= SNDOUT_EARC_OUTPUT_SET_USE && codec_type >= SNDOUT_EARC_CODEC_PCM && codec_type <= SNDOUT_EARC_CODEC_MPEG4_AAC && channel_num >= SNDOUT_EARC_CHNUM_MONO && channel_num <= SNDOUT_EARC_CHNUM_8 && (sample_rate == SNDOUT_EARC_SAMPLERATE_32 || sample_rate == SNDOUT_EARC_SAMPLERATE_44_1 || sample_rate == SNDOUT_EARC_SAMPLERATE_48 || sample_rate == SNDOUT_EARC_SAMPLERATE_88_2 || sample_rate == SNDOUT_EARC_SAMPLERATE_96 || sample_rate == SNDOUT_EARC_SAMPLERATE_176_4 || sample_rate == SNDOUT_EARC_SAMPLERATE_192) && mix_option >= SNDOUT_EARC_MIXOPTION_NONE && mix_option <= SNDOUT_EARC_MIXOPTION_ALL) { earc_output.set_type = set_type; earc_output.codec_type = codec_type; earc_output.channel_num = channel_num; earc_output.sample_rate = sample_rate; earc_output.mix_option = mix_option; memcpy(&proc_info_storage.earc_output_s, &earc_output, sizeof(earc_output)); audio_proc_ioctl_update(EARC_OUTPUT_E, &proc_info_storage); memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_EARC_OUTPUT_TYPE=%d %d %d %d %d", set_type, codec_type, channel_num, sample_rate, sample_rate); control_utils(env); return 0; } return -1; } static int sndout_eac3_atmos_encode_onoff_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_eac3_atmos_encode_onoff_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = eac3_atmos_encode_onoff; return 0; } static int sndout_eac3_atmos_encode_onoff_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int on_off = ucontrol->value.integer.value[0]; ALOGD("on_off=%d\n", on_off); if (on_off == 0 || on_off == 1) { eac3_atmos_encode_onoff = on_off; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_EAC3_ATMOS_ENCODE_ONOFF=%d", on_off == 0); control_utils(env); return 0; } return -1; } static int sndout_optic_output_type_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 5; uinfo->write_count = 5; return 0; } static int sndout_optic_output_type_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = optic_output.set_type; ucontrol->value.integer.value[1] = optic_output.codec_type; ucontrol->value.integer.value[2] = optic_output.channel_num; ucontrol->value.integer.value[3] = optic_output.sample_rate; ucontrol->value.integer.value[4] = optic_output.mix_option; return 0; } static int sndout_optic_output_type_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int set_type = ucontrol->value.integer.value[0]; int codec_type = ucontrol->value.integer.value[1]; int channel_num = ucontrol->value.integer.value[2]; int sample_rate = ucontrol->value.integer.value[3]; int mix_option = ucontrol->value.integer.value[4]; ALOGD("set_type=%d codec_type=%d channel_num=%d sample_rate=%d mix_option=%d\n", set_type, codec_type, channel_num, sample_rate, mix_option); if (set_type >= SNDOUT_OUTPUT_SET_NONE && set_type <= SNDOUT_OUTPUT_SET_USE && codec_type >= SNDOUT_CODEC_PCM && codec_type <= SNDOUT_CODEC_MPEG4_AAC && channel_num >= SNDOUT_CHNUM_MONO && channel_num <= SNDOUT_CHNUM_8 && (sample_rate == SNDOUT_SAMPLERATE_32 || sample_rate == SNDOUT_SAMPLERATE_44_1 || sample_rate == SNDOUT_SAMPLERATE_48 || sample_rate == SNDOUT_SAMPLERATE_88_2 || sample_rate == SNDOUT_SAMPLERATE_96 || sample_rate == SNDOUT_SAMPLERATE_176_4 || sample_rate == SNDOUT_SAMPLERATE_192) && mix_option >= SNDOUT_MIXOPTION_NONE && mix_option <= SNDOUT_MIXOPTION_ALL) { optic_output.set_type = set_type; optic_output.codec_type = codec_type; optic_output.channel_num = channel_num; optic_output.sample_rate = sample_rate; optic_output.mix_option = mix_option; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_OPTIC_OUTPUT_TYPE=%d %d %d %d %d", set_type, codec_type, channel_num, sample_rate, sample_rate); control_utils(env); return 0; } return -1; } static int sndout_arc_output_type_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 5; uinfo->write_count = 5; return 0; } static int sndout_arc_output_type_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = arc_output.set_type; ucontrol->value.integer.value[1] = arc_output.codec_type; ucontrol->value.integer.value[2] = arc_output.channel_num; ucontrol->value.integer.value[3] = arc_output.sample_rate; ucontrol->value.integer.value[4] = arc_output.mix_option; return 0; } static int sndout_arc_output_type_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int set_type = ucontrol->value.integer.value[0]; int codec_type = ucontrol->value.integer.value[1]; int channel_num = ucontrol->value.integer.value[2]; int sample_rate = ucontrol->value.integer.value[3]; int mix_option = ucontrol->value.integer.value[4]; ALOGD("set_type=%d codec_type=%d channel_num=%d sample_rate=%d mix_option=%d\n", set_type, codec_type, channel_num, sample_rate, mix_option); if (set_type >= SNDOUT_OUTPUT_SET_NONE && set_type <= SNDOUT_OUTPUT_SET_USE && codec_type >= SNDOUT_CODEC_PCM && codec_type <= SNDOUT_CODEC_MPEG4_AAC && channel_num >= SNDOUT_CHNUM_MONO && channel_num <= SNDOUT_CHNUM_8 && (sample_rate == SNDOUT_SAMPLERATE_32 || sample_rate == SNDOUT_SAMPLERATE_44_1 || sample_rate == SNDOUT_SAMPLERATE_48 || sample_rate == SNDOUT_SAMPLERATE_88_2 || sample_rate == SNDOUT_SAMPLERATE_96 || sample_rate == SNDOUT_SAMPLERATE_176_4 || sample_rate == SNDOUT_SAMPLERATE_192) && mix_option >= SNDOUT_MIXOPTION_NONE && mix_option <= SNDOUT_MIXOPTION_ALL) { arc_output.set_type = set_type; arc_output.codec_type = codec_type; arc_output.channel_num = channel_num; arc_output.sample_rate = sample_rate; arc_output.mix_option = mix_option; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_ARC_OUTPUT_TYPE=%d %d %d %d %d", set_type, codec_type, channel_num, sample_rate, sample_rate); control_utils(env); return 0; } return -1; } static int sndout_capture_path_point_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int sndout_capture_path_point_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = capture_path; return 0; } static int sndout_capture_path_point_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; int path = ucontrol->value.integer.value[0]; ALOGD("path=%d\n", path); if (path >= SNDOUT_CAPTURE_PATH_DEFAULT && path <= SNDOUT_CAPTURE_PATH_OUT_DAFC) { capture_path = path; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "SNDOUT_CAPTURE_PATH_POINT=%d", path); control_utils(env); return 0; } return -1; } static int audio_dolby_ms12_iidk_version_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READ; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 0; return 0; } static int audio_dolby_ms12_iidk_version_get(struct aml_ahal_ctl_elem_value *ucontrol) { // Get the Version of Dolby MS12 IIDK ucontrol->value.integer.value[0] = MS12_MAJOR_VERSION; ucontrol->value.integer.value[1] = MS12_MINOR_VERSION; return 0; } long aenc_info_param[3]; static int aenc_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 3; uinfo->write_count = 3; return 0; } static int aenc_info_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = aenc_info_param[0]; ucontrol->value.integer.value[1] = aenc_info_param[1]; ucontrol->value.integer.value[2] = aenc_info_param[2]; return 0; } static int aenc_info_put(struct aml_ahal_ctl_elem_value *ucontrol) { char env[MAX_UEVENT_LEN]; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "AENC_INFO=%ld %ld %ld", ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], ucontrol->value.integer.value[2]); control_utils(env); aenc_info_param[0] = ucontrol->value.integer.value[0]; aenc_info_param[1] = ucontrol->value.integer.value[1]; aenc_info_param[2] = ucontrol->value.integer.value[2]; return 0; } static int aenc_volume_param; static int aenc_volume_info(struct aml_ahal_ctl_elem_info *uinfo) { uinfo->access = AHAL_CTL_EXT_ACCESS_READWRITE; uinfo->type = AML_CTL_ELEM_TYPE_INTEGER; uinfo->element_count = 1; uinfo->write_count = 1; return 0; } static int aenc_volume_get(struct aml_ahal_ctl_elem_value *ucontrol) { ucontrol->value.integer.value[0] = aenc_volume_param; return 0; } static int aenc_volume_put(struct aml_ahal_ctl_elem_value *ucontrol) { int temp = ucontrol->value.integer.value[0]; char env[MAX_UEVENT_LEN]; aenc_volume_param = temp; memset(env, 0, sizeof(env)); snprintf(env, MAX_UEVENT_LEN, "AENC_VOLUME=%ld", ucontrol->value.integer.value[0]); control_utils(env); return 0; } static aml_kctl_func_new_t aml_lge_controls[] = { { .name = GAIN_OUTPUT, .info = gain_output_info, .get = gain_output_get, .put = gain_output_put, }, { .name = GAIN_INPUT, .info = gain_input_info, .get = gain_input_get, .put = gain_input_put, }, { .name = GAIN_INPUT_DURATION, .info = gain_input_duration_info, .get = gain_input_duration_info_get, .put = gain_input_duration_info_put, }, { .name = SOUND_ENGINE_LITE_VOLUME_PARAM, .info = Sound_Engine_Lite_Volume_Param_info, .get = Sound_Engine_Lite_Volume_Param_get, .put = Sound_Engine_Lite_Volume_Param_put, }, { .name = MUTE_INPUT, .info = mute_input_info, .get = mute_input_get, .put = mute_input_put, }, { .name = MUTE_OUTPUT, .info = mute_output_info, .get = mute_output_get, .put = mute_output_put, }, { .name = DELAY_INPUTOUTPUT, .info = delay_inputoutput_info, .get = delay_inputoutput_get, .put = delay_inputoutput_put, }, { .name = AUDIO_LATENCY_TIME, .info = audio_latency_info, .get = audio_latency_get, .put = audio_latency_put, }, { .name = LOW_LATENCY_MODE, .info = audio_low_latency_mode_info, .get = audio_low_latency_mode_get, .put = audio_low_latency_mode_put, }, { .name = GAIN_AUDIODESCRIPTION, .info = gain_audiodescription_info, .get = gain_audiodescription_get, .put = gain_audiodescription_put, }, { .name = ADC_OPEN, .info = adc_open_info, .get = adc_open_get, .put = adc_open_put, }, { .name = ADC_CLOSE, .info = adc_close_info, .get = adc_close_get, .put = adc_close_put, }, { .name = ADC_CONNECT, .info = adc_connect_info, .get = adc_connect_get, .put = adc_connect_put, }, { .name = ADC_DISCONNECT, .info = adc_disconnect_info, .get = adc_disconnect_get, .put = adc_disconnect_put, }, { .name = ADEC_OPEN, .info = adec_open_info, .get = adec_open_get, .put = adec_open_put, }, { .name = ADEC_CLOSE, .info = adec_close_info, .get = adec_close_get, .put = adec_close_put, }, { .name = ADEC_CONNECT, .info = adec_connect_info, .get = adec_connect_get, .put = adec_connect_put, }, { .name = ADEC_DISCONNECT, .info = adec_disconnect_info, .get = adec_disconnect_get, .put = adec_disconnect_put, }, { .name = ADEC_DOWNMIXMODE, .info = adec_downmix_mode_info, .get = adec_downmix_mode_get, .put = adec_downmix_mode_put, }, { .name = ADEC_CODEC, .info = adec_codec_info, .get = adec_codec_get, .put = adec_codec_put, }, { .name = ADEC_START, .info = adec_start_info, .get = adec_start_get, .put = adec_start_put, }, { .name = ADEC_STOP, .info = adec_stop_info, .get = adec_stop_get, .put = adec_stop_put, }, { .name = ADEC_MAXCAPACITY, .info = adec_maxcapacity_info, .get = adec_maxcapacity_get, .put = adec_maxcapacity_put, }, { .name = ADEC_USERMAXCAPACITY, .info = adec_usermaxcapacity_info, .get = adec_usermaxcapacity_get, .put = adec_usermaxcapacity_put, }, { .name = ADEC_TP_DECODER_OUTPUTMODE, .info = adec_decoder_outputmode_info, .get = adec_decoder_outputmode_get, .put = adec_decoder_outputmode_put, }, { .name = ADEC_SYNCMODE, .info = adec_syncmode_info, .get = adec_syncmode_get, .put = adec_syncmode_put, }, { .name = ADEC_DOLBYDRCMODE, .info = adec_dolby_drcmode_info, .get = adec_dolby_drcmode_get, .put = adec_dolby_drcmode_put, }, { .name = ADEC0_INFO, .info = adec0_info_info, .get = adec0_info_get, .put = adec0_info_put, }, { .name = ADEC1_INFO, .info = adec1_info_info, .get = adec1_info_get, .put = adec1_info_put, }, { .name = ADEC_DEFAULTPRL, .info = adec_default_prl_info, .get = adec_default_prl_get, .put = adec_default_prl_put, }, { .name = ADEC_TRICKMODE, .info = adec_trick_mode_info, .get = adec_trick_mode_get, .put = adec_trick_mode_put, }, { .name = ADEC_TP_AUDIODESCRIPTION, .info = adec_audiodescription_info, .get = adec_audiodescription_get, .put = adec_audiodescription_put, }, { .name = ADEC0_TP_PTS, .info = adec0_tp_pts_info, .get = adec0_tp_pts_get, .put = adec0_tp_pts_put, }, { .name = ADEC1_TP_PTS, .info = adec1_tp_pts_info, .get = adec1_tp_pts_get, .put = adec1_tp_pts_put, }, { .name = ADEC_AC4_AUTO1STLANG, .info = adec_ac4_auto1stlang_info, .get = adec_ac4_auto1stlang_get, .put = adec_ac4_auto1stlang_put, }, { .name = ADEC_AC4_AUTO2NDLANG, .info = adec_ac4_auto2ndlang_info, .get = adec_ac4_auto2ndlang_get, .put = adec_ac4_auto2ndlang_put, }, { .name = ADEC_AC4_AUTO_ADTYPE, .info = adec_ac4_ad_type_info, .get = adec_ac4_ad_type_get, .put = adec_ac4_ad_type_put, }, { .name = ADEC_AC4_AUTO_PRIORITIZE_ADTYPE, .info = adec_ac4_prioritize_ad_type_info, .get = adec_ac4_prioritize_ad_type_get, .put = adec_ac4_prioritize_ad_type_put, }, { .name = ADEC_AC4_DIALOGENHANCEGAIN, .info = adec_ac4_dialogenhance_gain_info, .get = adec_ac4_dialogenhance_gain_get, .put = adec_ac4_dialogenhance_gain_put, }, { .name = ADEC_AC4_AUTO_ADMIXING, .info = adec_ac4_admixing_info, .get = adec_ac4_admixing_get, .put = adec_ac4_admixing_put, }, { .name = ADEC_AC4_PRES_GROUP_IDX, .info = adec_ac4_pres_group_idx_info, .get = adec_ac4_pres_group_idx_get, .put = adec_ac4_pres_group_idx_put, },{ .name = ADEC_DOLBY_OTTMODE, .info = adec_dolby_ottmode_info, .get = adec_dolby_ottmode_get, .put = adec_dolby_ottmode_put, }, { .name = ADEC0_TP_BUFFERSTATUS, .info = adec0_tp_bufferstatus_info, .get = adec0_tp_bufferstatus_get, .put = adec0_tp_bufferstatus_put, }, { .name = ADEC1_TP_BUFFERSTATUS, .info = adec1_tp_bufferstatus_info, .get = adec1_tp_bufferstatus_get, .put = adec1_tp_bufferstatus_put, }, { .name = ADEC_AC4_ASSOCIATE_AUDIO_VOLUME, .info = adec_ac4_associate_volume_info, .get = adec_ac4_associate_volume_get, .put = adec_ac4_associate_volume_put, }, { .name = ADEC_LIPSYNC_OFFSET, .info = adec_lipsync_offset_info, .get = adec_lipsync_offset_get, .put = adec_lipsync_offset_put, }, { .name = ADEC_MASTER_SYNCMODE, .info = adec_master_syncmode_info, .get = adec_master_syncmode_get, .put = adec_master_syncmode_put, }, { .name = SNDOUT_OPEN, .info = sndout_open_info, .get = sndout_open_get, .put = sndout_open_put, }, { .name = SNDOUT_CLOSE, .info = sndout_close_info, .get = sndout_close_get, .put = sndout_close_put, }, { .name = SNDOUT_CONNECT, .info = sndout_connect_info, .get = sndout_connect_get, .put = sndout_connect_put, }, { .name = SNDOUT_DISCONNECT, .info = sndout_disconnect_info, .get = sndout_disconnect_get, .put = sndout_disconnect_put, }, { .name = SNDOUT_MAINAUDIO_OUTPUT, .info = sndout_mainaudio_output_info, .get = sndout_mainaudio_output_get, .put = sndout_mainaudio_output_put, }, { .name = SNDOUT_SPDIF_OUTPUTTYPE, .info = sndout_spdif_output_type_info, .get = sndout_spdif_output_type_get, .put = sndout_spdif_output_type_put, }, #if 0 { .name = SNDOUT_SPDIF_COPYPROTECTIONINFO, .info = sndout_spdif_cp_info, .get = sndout_spdif_cp_get, .put = sndout_spdif_cp_put, }, { .name = SNDOUT_SPDIF_CATERGORYCODE, .info = sndout_category_code_info, .get = sndout_category_code_get, .put = sndout_category_code_put, }, #endif { .name = SNDOUT_OPTIC_LIGHTONOFF, .info = sndout_optic_light_onoff_info, .get = sndout_optic_light_onoff_get, .put = sndout_optic_light_onoff_put, }, #if 0 { .name = SNDOUT_ARC_ONOFF, .info = sndout_arc_onoff_info, .get = sndout_arc_onoff_get, .put = sndout_arc_onoff_put, }, #endif { .name = SNDOUT_OPTIC_LG, .info = sndout_optic_lg_info, .get = sndout_optic_lg_get, .put = sndout_optic_lg_put, }, { .name = SNDOUT_SPK_OUTPUT, .info = sndout_spk_output_info, .get = sndout_spk_output_get, .put = sndout_spk_output_put, }, { .name = SNDOUT_CAPTURE_DISABLE, .info = sndout_capture_disable_info, .get = sndout_capture_disable_get, .put = sndout_capture_disable_put, }, { .name = SNDOUT_CAPTURE_INPUT_TIMECLOCK, .info = sndout_capture_input_clock_info, .get = sndout_capture_input_clock_get, .put = sndout_capture_input_clock_put, }, { .name = SNDOUT_CAPTURE_OUTPUT_RESAMPLING, .info = sndout_capture_output_resampling_info, .get = sndout_capture_output_resampling_get, .put = sndout_capture_output_resampling_put, }, #if 0 { .name = SNDOUT_EARC_ONOFF, .info = sndout_earc_onoff_info, .get = sndout_earc_onoff_get, .put = sndout_earc_onoff_put, }, #endif { .name = SNDOUT_EARC_OUTPUT_TYPE, .info = sndout_earc_output_type_info, .get = sndout_earc_output_type_get, .put = sndout_earc_output_type_put, }, { .name = SNDOUT_EAC3_ATMOS_ENCODE_ONOFF, .info = sndout_eac3_atmos_encode_onoff_info, .get = sndout_eac3_atmos_encode_onoff_get, .put = sndout_eac3_atmos_encode_onoff_put, }, { .name = SNDOUT_OPTIC_OUTPUT_TYPE, .info = sndout_optic_output_type_info, .get = sndout_optic_output_type_get, .put = sndout_optic_output_type_put, }, { .name = SNDOUT_ARC_OUTPUT_TYPE, .info = sndout_arc_output_type_info, .get = sndout_arc_output_type_get, .put = sndout_arc_output_type_put, }, { .name = SNDOUT_CAPTURE_PATH_POINT, .info = sndout_capture_path_point_info, .get = sndout_capture_path_point_get, .put = sndout_capture_path_point_put, }, { .name = DOLBY_MS12_IIDK_VERSION, .info = audio_dolby_ms12_iidk_version_info, .get = audio_dolby_ms12_iidk_version_get, }, { .name = AENC_INFO, .info = aenc_info, .get = aenc_info_get, .put = aenc_info_put, }, { .name = AENC_VOLUME, .info = aenc_volume_info, .get = aenc_volume_get, .put = aenc_volume_put, } }; int lge_get_kctl_common_param(int kctl_param, aml_ahal_ioctl_info_t *param) { //aml_ahal_ioctl_info_t *aml_lge_param = (aml_ahal_ioctl_info_t*)param; switch (kctl_param) { case AUDIO_IOCTL_CMD_KCONTROL_COUNT_READ: param->total_count = LGEParamCount; //ALOGI("The count is %d", aml_lge_param->total_count); break; default: ALOGE("unsupported kctl_param=%d", kctl_param); return -ENOTSUP; } return 0; } int aml_kctl_get_by_index(int index, aml_kctl_func_new_t *aml_kctl_fuc_t) { if (!aml_kctl_fuc_t) { ALOGE("error: aml_kctl_fuc_t is NULL\n"); return -EINVAL; } size_t arr_len = sizeof(aml_lge_controls) / sizeof(aml_lge_controls[0]); if (index < 0 || (size_t)index >= arr_len) { ALOGE("error: invalid index=%d (valid range: 0~%zu)\n", index, arr_len - 1); return -EINVAL; } *aml_kctl_fuc_t = aml_lge_controls[index]; ALOGE("success: get index=%d, name=%s\n", index, aml_kctl_fuc_t->name); return 0; } int aml_kctl_func(int cmd, void *param, int size) { aml_ahal_ioctl_info_t *aml_lge_param = (aml_ahal_ioctl_info_t*)param; aml_kctl_func_new_t lge_tmp_func; if (aml_lge_param->project != AUDIO_IOCTL_PROJECT_L) { ALOGE("error: not lge project %d\n", aml_lge_param->project); return -EINVAL; } if (cmd == AUDIO_IOCTL_CMD_KCONTROL_WRITE) { aml_kctl_get_by_index(aml_lge_param->index, &lge_tmp_func); lge_tmp_func.put(&aml_lge_param->value_cur); } else if (cmd == AUDIO_IOCTL_CMD_KCONTROL_READ) { aml_kctl_get_by_index(aml_lge_param->index, &lge_tmp_func); lge_tmp_func.get(&aml_lge_param->value_cur); ALOGI("value_get is %ld", aml_lge_param->value_cur.value.integer.value[5]); } else if (cmd == AUDIO_IOCTL_CMD_KCONTROL_INFO_READ) { aml_kctl_get_by_index(aml_lge_param->index, &lge_tmp_func); lge_tmp_func.info(&aml_lge_param->value_info); strncpy(aml_lge_param->value_info.name, aml_lge_controls[aml_lge_param->index].name, sizeof(aml_lge_param->value_info.name) - 1); ALOGI("THE COUNT IS %s", aml_lge_param->value_info.name); } else if (cmd == AUDIO_IOCTL_CMD_KCONTROL_COUNT_READ) { lge_get_kctl_common_param(AUDIO_IOCTL_CMD_KCONTROL_COUNT_READ, param); } return 0; }