static int dex_update_audio(int data)
{
	struct msm_dex_command dex = {
		.cmd = PCOM_UPDATE_AUDIO,
		.has_data = 1,
		.data = data,
	};

	msm_proc_comm_wince(&dex, 0);

	return 0;
}

static int dex_update_audio_done(void) {
	struct msm_dex_command dex = {
		.cmd = PCOM_UPDATE_AUDIO,
		.has_data = 1,
		.data = DEX_AUDIO_DONE,
	};
	D("%s\n", __func__);
	return msm_proc_comm_wince(&dex, 0);
}

static int update_audio_setting(void __user *arg)
{
    int ret = -EFAULT;
    struct audio_update_req req;

	if (copy_from_user(&req, arg, sizeof(struct audio_update_req))) {
		ERR_COPY_FROM_USER();
		return -EFAULT;
	} else {
        switch (req.type) {
            case PCOM_UPDATE_REQ:
                ret = dex_update_audio(req.value);
            break;

            case ADIE_FORCE8K_REQ:
                ADIE_Force8k( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_FORCE_ADIE_AWAKE_REQ:
                ADIE_ForceADIEAwake( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_FORCE_ADIE_UPDATE_REQ:
                ADIE_ForceADIEUpdate( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_UPDATE_AUDIO_METHOD:
                ADIE_UpdateAudioMethod( (req.value)?true:false );
                ret = 0;
            break;

            default:
            break;
        }
    }
    return ret;
}

static int turn_mic_bias_on_internal(bool on, bool bDualMicEn)
{
	if (amss_data->mic_bias_callback)
		amss_data->mic_bias_callback(on);

	dex_update_audio_done();
	
	return 0;
}

int turn_mic_bias_on(bool on)
{
	return turn_mic_bias_on_internal(on, false);
}
EXPORT_SYMBOL(turn_mic_bias_on);

static int update_hw_audio_path(void __user *arg)
{
	struct msm_audio_path audio_path;

	if (copy_from_user(&audio_path, arg, sizeof(audio_path))) {
		ERR_COPY_FROM_USER();
		return -EFAULT;
	}

	D("%s: mic=%d, dual_mic=%d, speaker=%d, headset = %d\n",
			__func__,
	       audio_path.enable_mic, audio_path.enable_dual_mic,
	       audio_path.enable_speaker, audio_path.enable_headset);

	/* Switch microphone on/off */
	turn_mic_bias_on_internal(audio_path.enable_mic,
                     audio_path.enable_dual_mic);

	/* Switch headset HW on/off */
	headphone_amp_power(audio_path.enable_headset);

	/* Switch Speaker HW on/off */
	speaker_amp_power(audio_path.enable_speaker);

	return 0;
}

static int acoustic_open(struct inode *inode, struct file *file)
{
	D("%s\n", __func__);
	return 0;
}
static int dex_update_audio(int data)
{
	struct msm_dex_command dex = {
		.cmd = PCOM_UPDATE_AUDIO,
		.has_data = 1,
		.data = data,
	};

	msm_proc_comm_wince(&dex, 0);

	return 0;
}

static int dex_update_audio_done(void) {
	struct msm_dex_command dex = {
		.cmd = PCOM_UPDATE_AUDIO,
		.has_data = 1,
		.data = DEX_AUDIO_DONE,
	};
	D("%s\n", __func__);
	return msm_proc_comm_wince(&dex, 0);
}

static int update_audio_setting(void __user *arg)
{
    int ret = -EFAULT;
    struct audio_update_req req;

	if (copy_from_user(&req, arg, sizeof(struct audio_update_req))) {
		ERR_COPY_FROM_USER();
		return -EFAULT;
	} else {
        switch (req.type) {
            case PCOM_UPDATE_REQ:
                ret = dex_update_audio(req.value);
            break;

            case ADIE_FORCE8K_REQ:
                ADIE_Force8k( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_FORCE_ADIE_AWAKE_REQ:
                ADIE_ForceADIEAwake( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_FORCE_ADIE_UPDATE_REQ:
                ADIE_ForceADIEUpdate( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_UPDATE_AUDIO_METHOD:
                ADIE_UpdateAudioMethod( (req.value)?true:false );
                ret = 0;
            break;

            default:
            break;
        }
    }
    return ret;
}

static int turn_mic_bias_on_internal(bool on, bool bDualMicEn)
{
	char pmSpeakerGain[2][10] = { 
			{0x93, 0, 0x93, 7, 0x93, 1, 0x93, 7, 0xFF, 0xFF},
			{0x93, 0, 0x93, 4, 0x93, 1, 0x93, 4, 0xFF, 0xFF} };


	D("%s(%d)\n", __func__, on);

	/* enable handset mic */
/* r0bin: photon doesnt have mic offset, or at least it wasnt found yet. 
 * uncomment those line is safe, we enable mic with pmic_en below
 *
	if ( machine_is_htcrhodium() && bDualMicEn && on ) {
		memcpy(amss_data->mic_offset, pmSpeakerGain[1], 10);
	} else {
		writel(0xffff0080 | (on ? 0x100 : 0), amss_data->mic_offset);   
	}
	dex_update_audio_done();

	if ( machine_is_htcrhodium() ) {
		if ( bDualMicEn && on ) {
			ADC3001_wakeup();
		} else {
			ADC3001_powerdown();
		}
	}
*/
	if (amss_data->mic_bias_callback)
		amss_data->mic_bias_callback(on);

	dex_update_audio_done();
	
	return 0;
}
static int dex_update_audio(int data)
{
	struct msm_dex_command dex = {
		.cmd = DEX_UPDATE_AUDIO,
		.has_data = 1,
		.data = data,
	};
	msm_dex_comm(&dex, 0);

	return 0;
}

static int dex_update_audio_done(void) {
	struct msm_dex_command dex = {
		.cmd = DEX_UPDATE_AUDIO,
		.has_data = 1,
		.data = DEX_AUDIO_DONE,
	};
	D("%s\n", __func__);
	return msm_dex_comm(&dex, 0);
}

static int update_audio_setting(void __user *arg)
{
    int ret = -EFAULT;
    struct audio_update_req req;

	if (copy_from_user(&req, arg, sizeof(struct audio_update_req))) {
		ERR_COPY_FROM_USER();
		return -EFAULT;
	} else {
        switch (req.type) {
            case PCOM_UPDATE_REQ:
                ret = dex_update_audio(req.value);
            break;

            case ADIE_FORCE8K_REQ:
                ADIE_Force8k( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_FORCE_ADIE_AWAKE_REQ:
                ADIE_ForceADIEAwake( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_FORCE_ADIE_UPDATE_REQ:
                ADIE_ForceADIEUpdate( (req.value)?true:false );
                ret = 0;
            break;

            case ADIE_UPDATE_AUDIO_METHOD:
                ADIE_UpdateAudioMethod( (req.value)?true:false );
                ret = 0;
            break;

            default:
            break;
        }
    }
    return ret;
}

static int turn_mic_bias_on(bool on, bool enable_dualmic)
{

	D("%s(%d)\n", __func__, on);

	/* enable handset mic */
	writel(0xffff0080 | (on ? 0x100 : 0), amss_data->mic_offset);
	dex_update_audio_done();

	if (amss_data->mic_bias_callback)
		amss_data->mic_bias_callback(on, enable_dualmic);

	return 0;
}