/*
 * wait until calibration impedance is ok
 *  operate on all devices that have a handle open
 */
static void waitCalibration(Tfa98xx_handle_t handle, float *pRe25)
{
        Tfa98xx_Error_t err;
        int calibrateDone, count = 500;

        assert(pRe25 != NULL);

        err = Tfa98xx_DspReadMem(handle, 231, 1, &calibrateDone);
        assert(err == Tfa98xx_Error_Ok);
        while ((calibrateDone == 0) && (count-- > 0))   // TODO protect loop with timeout?
        {
                err = Tfa98xx_DspReadMem(handle, 231, 1, &calibrateDone);
                assert(err == Tfa98xx_Error_Ok);
        }
        err = Tfa98xx_DspGetCalibrationImpedance(handle, pRe25);
        assert(err == Tfa98xx_Error_Ok);

}
static int mono_speaker_on(
	int channel,
	struct tfa98xx_param_data *speaker,
	struct tfa98xx_param_data *config,
	struct tfa98xx_param_data *preset,
	struct tfa98xx_param_data *eq)
{
	enum Tfa98xx_Error err;
	FIXEDPT re25;
	int calibrateDone = 0;

	/* use the generic slave address for optimizations */

	coldStartup(handles[channel]);
	/*Set to calibration once*/
	/* Only needed for really first time calibration */
	setOtc(handles[channel], 1);

	/* Check if MTPEX bit is set for calibration once mode */
	if (checkMTPEX(handles[channel]) == 0) {
		pr_info("%s: DSP not yet calibrated. Calibration will start\n",
			__func__);

		/* ensure no audio during special calibration */
		err = Tfa98xx_SetMute(handles[channel], Tfa98xx_Mute_Digital);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_ReadRegister16 failed\n",
				__func__);
			return -EINVAL;
		}
	} else
		pr_info("%s: DSP already calibrated\n", __func__);

	/* load predefined, or fullmodel from file */
	setSpeaker(1, &handles[channel], speaker);
	/* load the settings */
	setConfig(1, &handles[channel], config);
	/* load a preset */
	setPreset(1, &handles[channel], preset);
	/* set the equalizer */
	setEQ(1, &handles[channel], eq);

	err = Tfa98xx_SelectChannel(handles[channel], Tfa98xx_Channel_L_R);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_SelectChannel failed\n", __func__);
		return -EINVAL;
	}

	/* all settings loaded, signal the DSP to start calibration */
	err = Tfa98xx_SetConfigured(handles[channel]);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_SetConfigured failed\n", __func__);
		return -EINVAL;
	}

	waitCalibration(handles[channel], &calibrateDone);
	if (calibrateDone)
		Tfa98xx_DspGetCalibrationImpedance(handles[channel], &re25);
	else {
		re25 = 0;
		err = Tfa98xx_Powerdown(handles[channel], 1);
		pr_err("%s: Tfa98xx_Powerdown failed, channel=%d\n",
			__func__, channel);
		return -EINVAL;
	}

	err = Tfa98xx_SetMute(handles[channel], Tfa98xx_Mute_Off);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_SetMute failed, channel=%d\n",
			__func__, channel);
		return -EINVAL;
	}

	return 0;
}
static int stereo_speaker_on(
	struct tfa98xx_param_data *speaker[2],
	struct tfa98xx_param_data *config[2],
	struct tfa98xx_param_data *preset[2],
	struct tfa98xx_param_data *eq[2])
{
	enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
	unsigned char h;
	FIXEDPT re25;
	int calibrateDone = 0;

	/* use the generic slave address for optimizations */

	for (h = 0; h < 2; h++) {
		coldStartup(handles[h]);
		/*Set to calibration once*/
		/* Only needed for really first time calibration */
		setOtc(handles[h], 1);

		/* Check if MTPEX bit is set for calibration once mode */
		if (checkMTPEX(handles[h]) == 0) {
			pr_info("%s: DSP not yet calibrated. Calibration will"\
				" start\n", __func__);

			/* ensure no audio during special calibration */
			err = Tfa98xx_SetMute(
				handles[h], Tfa98xx_Mute_Digital);
			if (err != Tfa98xx_Error_Ok) {
				pr_err("%s: Tfa98xx_SetMute failed, h=%d\n",
					__func__, h);
				return -EINVAL;
			}
		} else
			pr_info("%s: DSP already calibrated\n", __func__);
	}

	/* load predefined, or fullmodel from data */
	for (h = 0; h < 2; h++)
		setSpeaker(1, &handles[h], speaker[h]);

	/* load the settings */
	for (h = 0; h < 2; h++)
		setConfig(1, &handles[h], config[h]);

	/* load a preset */
	for (h = 0; h < 2; h++)
		setPreset(1, &handles[h], preset[h]);

	/* set the equalizer */
	for (h = 0; h < 2; h++)
		setEQ(1, &handles[h], eq[h]);

	err = set_speaker_lr(handles, speaker_lr);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: set_speaker_lr failed\n", __func__);
		return err;
	}

	/* all settings loaded, signal the DSP to start calibration */
	for (h = 0; h < 2; h++) {
		err = Tfa98xx_SetConfigured(handles[h]);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_SetConfigured failed h=%d\n",
				__func__, h);
			return -EINVAL;
		}
	}

	for (h = 0; h < 2; h++) {
		calibrateDone = 0;
		waitCalibration(handles[h], &calibrateDone);
		if (calibrateDone)
			Tfa98xx_DspGetCalibrationImpedance(handles[h], &re25);
		else {
			re25 = 0;
			err = Tfa98xx_Powerdown(handles[h], 1);
			pr_err("%s: Calibration failed, power down" \
				" and return h=%d\n", __func__, h);
			return -EINVAL;
		}
		pr_info("%s re25:%016llx\n", __func__, re25);

		err = Tfa98xx_SetMute(handles[h], Tfa98xx_Mute_Off);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_SetMute failed, h=%d\n",
				__func__, h);
			return -EINVAL;
		}

	}

	return 0;
}