From cdc1a96ac05f2eb3e2fea69aa90a18ae3d5696cd Mon Sep 17 00:00:00 2001 From: Andrew Dodd Date: Sat, 10 Nov 2012 14:23:08 -0500 Subject: mc1n2: Opensource audio HAL from Replicant Thanks to Paul Kocialkowski of the Replicant project for this work. Original sources: https://gitorious.org/replicant/hardware_tinyalsa-audio http://git.paulk.fr/gitweb/?p=yamaha-mc1n2-audio.git;a=summary Change-Id: Ia3d89c67d64decb56e3d6518c5f382d38e5a1fa9 --- yamaha-mc1n2-audio/yamaha-mc1n2-audio.c | 674 ++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 yamaha-mc1n2-audio/yamaha-mc1n2-audio.c (limited to 'yamaha-mc1n2-audio/yamaha-mc1n2-audio.c') diff --git a/yamaha-mc1n2-audio/yamaha-mc1n2-audio.c b/yamaha-mc1n2-audio/yamaha-mc1n2-audio.c new file mode 100644 index 0000000..b39286f --- /dev/null +++ b/yamaha-mc1n2-audio/yamaha-mc1n2-audio.c @@ -0,0 +1,674 @@ +/* + * Copyright (C) 2012 Paul Kocialkowski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include +#include + +#include + +#define LOG_TAG "Yamaha-MC1N2-Audio" +#include + +#include + +#include + +struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platforms[] = { + &galaxys2_pdata, +}; + +int yamaha_mc1n2_audio_platforms_count = sizeof(yamaha_mc1n2_audio_platforms) / + sizeof(struct yamaha_mc1n2_audio_pdata *); + +/* + * IOCTL + */ + +int yamaha_mc1n2_audio_ioctl(struct yamaha_mc1n2_audio_pdata *pdata, + int command, struct mc1n2_ctrl_args *hw_ctrl) +{ + char *hw_node = NULL; + int hw_fd = -1; + int rc = -1; + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + hw_node = pdata->ops->hw_node; + if(hw_node == NULL) { + ALOGE("%s: error, missing hw_node!", __func__); + return -1; + } + + if(pdata->ops->hw_fd <= 0) { + hw_fd = open(hw_node, O_RDWR); + if(hw_fd < 0) { + ALOGE("%s: error, unable to open hw_node (fd is %d)!", __func__, hw_fd); + return -1; + } + + pdata->ops->hw_fd = hw_fd; + } + + rc = ioctl(pdata->ops->hw_fd, command, hw_ctrl); + if(rc < 0) { + ALOGE("%s: error, ioctl on hw_node failed (rc is %d)!", __func__, rc); + return -1; + } + + return rc; +} + +int yamaha_mc1n2_audio_ioctl_set_ctrl(struct yamaha_mc1n2_audio_pdata *pdata, + unsigned long command, void *data, unsigned long update_info) +{ + struct mc1n2_ctrl_args hw_ctrl; + + if(pdata == NULL) + return -1; + + memset(&hw_ctrl, 0, sizeof(hw_ctrl)); + hw_ctrl.dCmd = command; + hw_ctrl.pvPrm = data; + hw_ctrl.dPrm = update_info; + + return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_SET_CTRL, &hw_ctrl); +} + +int yamaha_mc1n2_audio_ioctl_notify(struct yamaha_mc1n2_audio_pdata *pdata, + unsigned long command) +{ + struct mc1n2_ctrl_args hw_ctrl; + + if(pdata == NULL) + return -1; + + memset(&hw_ctrl, 0, sizeof(hw_ctrl)); + hw_ctrl.dCmd = command; + + return yamaha_mc1n2_audio_ioctl(pdata, MC1N2_IOCTL_NOTIFY, &hw_ctrl); +} + +/* + * Routines + */ + +int yamaha_mc1n2_audio_init(struct yamaha_mc1n2_audio_pdata *pdata) +{ + struct yamaha_mc1n2_audio_params_init *params = NULL; + int rc = -1; + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + params = pdata->ops->params.init; + if(params == NULL) + return -1; + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC, + ¶ms->dac_info, 0x07); + if(rc < 0) { + ALOGE("SET_DAC IOCTL failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_ADC, + ¶ms->adc_info, 0x07); + if(rc < 0) { + ALOGE("SET_ADC IOCTL failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SP, + ¶ms->sp_info, 0x00); + if(rc < 0) { + ALOGE("SET_SP IOCTL failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PDM, + ¶ms->pdm_info, 0x7f); + if(rc < 0) { + ALOGE("SET_PDM IOCTL failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DNG, + ¶ms->dng_info, 0x3f3f3f); + if(rc < 0) { + ALOGE("SET_DNG IOCTL failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_SYSEQ, + ¶ms->syseq_info, 0x03); + if(rc < 0) { + ALOGE("SET_SYSEQ IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +struct yamaha_mc1n2_audio_params_route * + yamaha_mc1n2_audio_params_route_find(struct yamaha_mc1n2_audio_pdata *pdata, + audio_devices_t device, enum yamaha_mc1n2_audio_direction direction) +{ + struct yamaha_mc1n2_audio_params_route *params = NULL; + int params_count = 0; + int i; + + if(pdata == NULL || pdata->ops == NULL) + return NULL; + + ALOGD("(%s): device = %d, direction = %d",__func__,device,direction); + + params = pdata->ops->params.routes; + params_count = pdata->ops->params.routes_count; + if(params == NULL || params_count <= 0) + return NULL; + + for(i=0 ; i < params_count ; i++) { + if(params[i].device == device && params[i].direction == direction) + return ¶ms[i]; + } + + return NULL; +} + +int yamaha_mc1n2_audio_params_route_simple_array_merge(int length, + unsigned char *array_src, unsigned char *array_dst) +{ + int i; + + if(length <= 0 || array_src == NULL || array_dst == NULL) + return -1; + + for(i=0 ; i < length ; i++) { + if(array_dst[i] == 0) + array_dst[i] = array_src[i]; + } + + return 0; +} + +int yamaha_mc1n2_audio_params_route_path_array_merge(int length, + unsigned char *array_src, unsigned char *array_dst) +{ + int i, j; + unsigned char v; + + if(length <= 0 || array_src == NULL || array_dst == NULL) + return -1; + + for(i=0 ; i < length ; i++) { + if(array_dst[i] == 0) { + array_dst[i] = array_src[i]; + } else { + v = array_src[i]; + + for(j=0; j < 8 ; j++) { + if((1 << j) & array_dst[i]) { + if(j % 2 == 0) + v &= ~(1 << (j+1)); + else + v &= ~(1 << (j-1)); + + v |= (1 << j); + } + } + + array_dst[i] = v; + } + } + + return 0; +} + +int yamaha_mc1n2_audio_params_route_merge( + struct yamaha_mc1n2_audio_params_route *params_src, + struct yamaha_mc1n2_audio_params_route *params_dst) +{ + if(params_src == NULL || params_dst == NULL) + return -1; + + // ae_info + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.bOnOff), + ¶ms_src->ae_info.bOnOff, ¶ms_dst->ae_info.bOnOff); + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abBex), + params_src->ae_info.abBex, params_dst->ae_info.abBex); + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abWide), + params_src->ae_info.abWide, params_dst->ae_info.abWide); + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abDrc), + params_src->ae_info.abDrc, params_dst->ae_info.abDrc); + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abEq5), + params_src->ae_info.abEq5, params_dst->ae_info.abEq5); + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->ae_info.abEq3), + params_src->ae_info.abEq3, params_dst->ae_info.abEq3); + + // path_info + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asHpOut[0].abSrcOnOff), + params_src->path_info.asHpOut[0].abSrcOnOff, params_dst->path_info.asHpOut[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asHpOut[1].abSrcOnOff), + params_src->path_info.asHpOut[1].abSrcOnOff, params_dst->path_info.asHpOut[1].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asSpOut[0].abSrcOnOff), + params_src->path_info.asSpOut[0].abSrcOnOff, params_dst->path_info.asSpOut[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asSpOut[1].abSrcOnOff), + params_src->path_info.asSpOut[1].abSrcOnOff, params_dst->path_info.asSpOut[1].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asRcOut[0].abSrcOnOff), + params_src->path_info.asRcOut[0].abSrcOnOff, params_dst->path_info.asRcOut[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout1[0].abSrcOnOff), + params_src->path_info.asLout1[0].abSrcOnOff, params_dst->path_info.asLout1[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout1[1].abSrcOnOff), + params_src->path_info.asLout1[1].abSrcOnOff, params_dst->path_info.asLout1[1].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout2[0].abSrcOnOff), + params_src->path_info.asLout2[0].abSrcOnOff, params_dst->path_info.asLout2[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asLout2[1].abSrcOnOff), + params_src->path_info.asLout2[1].abSrcOnOff, params_dst->path_info.asLout2[1].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asPeak[0].abSrcOnOff), + params_src->path_info.asPeak[0].abSrcOnOff, params_dst->path_info.asPeak[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit0[0].abSrcOnOff), + params_src->path_info.asDit0[0].abSrcOnOff, params_dst->path_info.asDit0[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit1[0].abSrcOnOff), + params_src->path_info.asDit1[0].abSrcOnOff, params_dst->path_info.asDit1[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDit2[0].abSrcOnOff), + params_src->path_info.asDit2[0].abSrcOnOff, params_dst->path_info.asDit2[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDac[0].abSrcOnOff), + params_src->path_info.asDac[0].abSrcOnOff, params_dst->path_info.asDac[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asDac[1].abSrcOnOff), + params_src->path_info.asDac[1].abSrcOnOff, params_dst->path_info.asDac[1].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAe[0].abSrcOnOff), + params_src->path_info.asAe[0].abSrcOnOff, params_dst->path_info.asAe[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[0].abSrcOnOff), + params_src->path_info.asCdsp[0].abSrcOnOff, params_dst->path_info.asCdsp[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[1].abSrcOnOff), + params_src->path_info.asCdsp[1].abSrcOnOff, params_dst->path_info.asCdsp[1].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[2].abSrcOnOff), + params_src->path_info.asCdsp[2].abSrcOnOff, params_dst->path_info.asCdsp[2].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asCdsp[3].abSrcOnOff), + params_src->path_info.asCdsp[3].abSrcOnOff, params_dst->path_info.asCdsp[3].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc0[0].abSrcOnOff), + params_src->path_info.asAdc0[0].abSrcOnOff, params_dst->path_info.asAdc0[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc0[1].abSrcOnOff), + params_src->path_info.asAdc0[1].abSrcOnOff, params_dst->path_info.asAdc0[1].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asAdc1[0].abSrcOnOff), + params_src->path_info.asAdc1[0].abSrcOnOff, params_dst->path_info.asAdc1[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asMix[0].abSrcOnOff), + params_src->path_info.asMix[0].abSrcOnOff, params_dst->path_info.asMix[0].abSrcOnOff); + yamaha_mc1n2_audio_params_route_path_array_merge(sizeof(params_src->path_info.asBias[0].abSrcOnOff), + params_src->path_info.asBias[0].abSrcOnOff, params_dst->path_info.asBias[0].abSrcOnOff); + + // dac_info + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bMasterSwap), + ¶ms_src->dac_info.bMasterSwap, ¶ms_dst->dac_info.bMasterSwap); + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bVoiceSwap), + ¶ms_src->dac_info.bVoiceSwap, ¶ms_dst->dac_info.bVoiceSwap); + yamaha_mc1n2_audio_params_route_simple_array_merge(sizeof(params_src->dac_info.bDcCut), + ¶ms_src->dac_info.bDcCut, ¶ms_dst->dac_info.bDcCut); + + return 0; +} + +int yamaha_mc1n2_audio_route_start(struct yamaha_mc1n2_audio_pdata *pdata) +{ + struct yamaha_mc1n2_audio_params_route *params_route = NULL; + struct yamaha_mc1n2_audio_params_init *params_init = NULL; + struct yamaha_mc1n2_audio_params_route *params = NULL; + struct yamaha_mc1n2_audio_params_route params_src; + struct yamaha_mc1n2_audio_params_route params_dst; + + int rc; + + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + params_init = pdata->ops->params.init; + if(params_init == NULL) + return -1; + + // Copy the init params + memcpy(¶ms_src.ae_info, ¶ms_init->ae_info, sizeof(params_src.ae_info)); + memcpy(¶ms_src.path_info, ¶ms_init->path_info, sizeof(params_src.path_info)); + memcpy(¶ms_src.dac_info, ¶ms_init->dac_info, sizeof(params_src.dac_info)); + +output_merge: + if(pdata->output_state) { + params_route = yamaha_mc1n2_audio_params_route_find(pdata, + pdata->output_device, YAMAHA_MC1N2_AUDIO_DIRECTION_OUTPUT); + if(params_route == NULL) + goto input_merge; + + memcpy(¶ms_dst, params_route, sizeof(params_dst)); + yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst); + memcpy(¶ms_src, ¶ms_dst, sizeof(params_src)); + } + +input_merge: + if(pdata->input_state) { + params_route = yamaha_mc1n2_audio_params_route_find(pdata, + pdata->input_device, YAMAHA_MC1N2_AUDIO_DIRECTION_INPUT); + if(params_route == NULL) + goto modem_merge; + + memcpy(¶ms_dst, params_route, sizeof(params_dst)); + yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst); + memcpy(¶ms_src, ¶ms_dst, sizeof(params_src)); + } + +modem_merge: + if(pdata->modem_state) { + params_route = yamaha_mc1n2_audio_params_route_find(pdata, + pdata->output_device, YAMAHA_MC1N2_AUDIO_DIRECTION_MODEM); + if(params_route == NULL) + goto route_start; + + memcpy(¶ms_dst, params_route, sizeof(params_dst)); + yamaha_mc1n2_audio_params_route_merge(¶ms_src, ¶ms_dst); + memcpy(¶ms_src, ¶ms_dst, sizeof(params_src)); + } + +route_start: + params = &(params_src); + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_AUDIOENGINE, + ¶ms->ae_info, 0x0f); + if(rc < 0) { + ALOGE("SET_AUDIOENGINE IOCTL failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_PATH, + ¶ms->path_info, 0x00); + if(rc < 0) { + ALOGE("SET_PATH IOCTL failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_set_ctrl(pdata, MCDRV_SET_DAC, + ¶ms->dac_info, 0x07); + if(rc < 0) { + ALOGE("SET_DAC IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +int yamaha_mc1n2_audio_output_start(struct yamaha_mc1n2_audio_pdata *pdata) +{ + int rc; + + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + pdata->output_state = 1; + + rc = yamaha_mc1n2_audio_route_start(pdata); + if(rc < 0) { + ALOGE("Route start failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_START); + if(rc < 0) { + ALOGE("NOTIFY_MEDIA_PLAY_START IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +int yamaha_mc1n2_audio_output_stop(struct yamaha_mc1n2_audio_pdata *pdata) +{ + int rc; + + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + pdata->output_state = 0; + + rc = yamaha_mc1n2_audio_route_start(pdata); + if(rc < 0) { + ALOGE("Route start failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_MEDIA_PLAY_STOP); + if(rc < 0) { + ALOGE("NOTIFY_MEDIA_PLAY_STOP IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +int yamaha_mc1n2_audio_input_start(struct yamaha_mc1n2_audio_pdata *pdata) +{ + int rc; + + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + pdata->input_state = 1; + + rc = yamaha_mc1n2_audio_route_start(pdata); + if(rc < 0) { + ALOGE("Route start failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_VOICE_REC_START); + if(rc < 0) { + ALOGE("NOTIFY_VOICE_REC_START IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +int yamaha_mc1n2_audio_input_stop(struct yamaha_mc1n2_audio_pdata *pdata) +{ + int rc; + + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + pdata->input_state = 0; + + rc = yamaha_mc1n2_audio_route_start(pdata); + if(rc < 0) { + ALOGE("Route start failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_VOICE_REC_STOP); + if(rc < 0) { + ALOGE("NOTIFY_VOICE_REC_START IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +int yamaha_mc1n2_audio_modem_start(struct yamaha_mc1n2_audio_pdata *pdata) +{ + int rc; + + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + pdata->modem_state = 1; + + rc = yamaha_mc1n2_audio_route_start(pdata); + if(rc < 0) { + ALOGE("Route start failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_CALL_START); + if(rc < 0) { + ALOGE("NOTIFY_CALL_START IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +int yamaha_mc1n2_audio_modem_stop(struct yamaha_mc1n2_audio_pdata *pdata) +{ + int rc; + + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + pdata->modem_state = 0; + + rc = yamaha_mc1n2_audio_route_start(pdata); + if(rc < 0) { + ALOGE("Route start failed, aborting!"); + return -1; + } + + rc = yamaha_mc1n2_audio_ioctl_notify(pdata, MCDRV_NOTIFY_CALL_STOP); + if(rc < 0) { + ALOGE("NOTIFY_CALL_START IOCTL failed, aborting!"); + return -1; + } + + return 0; +} + +/* + * Values configuration + */ + +int yamaha_mc1n2_audio_set_route(struct yamaha_mc1n2_audio_pdata *pdata, + audio_devices_t device) +{ + int changed = 0; + + ALOGD("%s(%x)", __func__, device); + + if(pdata == NULL) + return -1; + + if(audio_is_output_device(device) && pdata->output_device != device) { + pdata->output_device = device; + changed = 1; + } else if(audio_is_input_device(device) && pdata->input_device != device) { + pdata->input_device = device; + changed = 1; + } + + if(changed && (pdata->output_state || pdata->input_state || pdata->modem_state)) + return yamaha_mc1n2_audio_route_start(pdata); + + return 0; +} + +char *yamaha_mc1n2_audio_get_hw_node(struct yamaha_mc1n2_audio_pdata *pdata) +{ + if(pdata == NULL) + return NULL; + + return pdata->ops->hw_node; +} + +/* + * Init/Deinit + */ + +struct yamaha_mc1n2_audio_pdata *yamaha_mc1n2_audio_platform_get( + char *device_name) +{ + int i; + + if(device_name == NULL) + return NULL; + + ALOGD("Found %d registered platforms", + yamaha_mc1n2_audio_platforms_count); + + for(i=0 ; i < yamaha_mc1n2_audio_platforms_count ; i++) { + if(yamaha_mc1n2_audio_platforms[i] != NULL && + yamaha_mc1n2_audio_platforms[i]->name != NULL) { + if(strcmp(yamaha_mc1n2_audio_platforms[i]->name, device_name) == 0) { + return yamaha_mc1n2_audio_platforms[i]; + } + } + } + + return NULL; +} + + +int yamaha_mc1n2_audio_start(struct yamaha_mc1n2_audio_pdata **pdata_p, + char *device_name) +{ + struct yamaha_mc1n2_audio_pdata *pdata = NULL; + int rc; + + ALOGD("%s(%s)", __func__, device_name); + + if(pdata_p == NULL || device_name == NULL) + return -1; + + pdata = yamaha_mc1n2_audio_platform_get(device_name); + if(pdata == NULL || pdata->ops == NULL) { + ALOGE("Unable to find requested platform: %s", device_name); + return -1; + } + + pdata->ops->hw_fd = -1; + + *pdata_p = pdata; + + return 0; +} + +int yamaha_mc1n2_audio_stop(struct yamaha_mc1n2_audio_pdata *pdata) +{ + ALOGD("%s()", __func__); + + if(pdata == NULL || pdata->ops == NULL) + return -1; + + if(pdata->ops->hw_fd >= 0) { + close(pdata->ops->hw_fd); + } + + return 0; +} -- cgit v1.1