int tfa98xxDiagLoadPresetsMultiple(int slave)
{
	Tfa98xx_handle_t hL, hR, handles[2] ;
	int result = 0; // 1 is failure
	Tfa98xx_Config_t cfg;
	unsigned char tstbuf[0x87 + sizeof(cfg)];

	TRACEIN;
	lastApiError = Tfa98xx_Open(slave << 1, &hL);
	if (lastApiError != Tfa98xx_Error_Ok)
		return 2;
	handles[0]=hL;
	lastApiError = Tfa98xx_Open(slave+1 << 1, &hR);
	if (lastApiError != Tfa98xx_Error_Ok)
		return 3;
	handles[1]=hR;


	lastApiError = Tfa98xx_DspWritePresetMultiple(2, handles, TFA98XX_PRESET_LENGTH,
			settings_HQ_KS_13X18_DUMBO_preset);
	assert(lastApiError == Tfa98xx_Error_Ok);


  stop:
	Tfa98xx_Close(hL);
	Tfa98xx_Close(hR);
	lastError = result;
	TRACEOUT;
	return result;
}
int tfa98xxDiagLoadPreset(int slave)
{
        Tfa98xx_handle_t handle;
        int result = 1;         // 1 is failure
        Tfa98xx_Config_t cfg;
        unsigned char tstbuf[0x87 + sizeof(cfg)];

        TRACEIN;
        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 2;

        coldStartup(handle);
        lastApiError =
            Tfa98xx_DspWritePreset(handle, TFA98XX_PRESET_LENGTH,
            			settings_HQ_KS_13X18_DUMBO_preset);
        assert(lastApiError == Tfa98xx_Error_Ok);

        lastApiError =
            Tfa98xx_DspGetParam(handle, 1 /*MODULE_SPEAKERBOOST */ , 0x80,
                                sizeof(tstbuf), tstbuf);
        assert(lastApiError == Tfa98xx_Error_Ok);

        result =
            0 != memcmp(settings_HQ_KS_13X18_DUMBO_preset, &tstbuf[sizeof(cfg)],
                        sizeof(Tfa98xx_Preset_t));
        if (result)
                sprintf(lastErrorString, "DSP parameters mismatch");

 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        TRACEOUT;
        return result;
}
/*
 * dump all known registers
 *   returns:
 *     0 if slave can't be opened
 *     nr of registers displayed
 */
int tfa98xxDiagRegisterDump(int slave)
{
        Tfa98xx_handle_t handle;
        int i;
        unsigned short regval;
        unsigned char reg;

        TRACEIN;

        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 0;

        for (i = 0; i < MAXREGS; i++) {
                lastApiError =
                    Tfa98xx_ReadRegister16(handle, regdefs[i].offset, &regval);
                assert(lastApiError == Tfa98xx_Error_Ok);
                printf("0x%02x: 0x%04x (%s)\n",
                       regdefs[i].offset, regval, regdefs[i].name);
        }

        Tfa98xx_Close(handle);

        TRACEOUT;
        return i;
}
int tfa98xxDiagLoadConfig(int slave)
{
        Tfa98xx_handle_t handle;
        int result = 1;         // 1 is failure
        Tfa98xx_Config_t cfg;

        TRACEIN;
        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 2;

        coldStartup(handle);
        lastApiError = Tfa98xx_DspWriteConfig(handle, TFA98XX_CONFIG_LENGTH,
        		settings_Setup87_config);
        assert(lastApiError == Tfa98xx_Error_Ok);

        lastApiError =
            Tfa98xx_DspGetParam(handle, 1 /*MODULE_SPEAKERBOOST */ , 0x80,
                                sizeof(cfg), cfg);
        assert(lastApiError == Tfa98xx_Error_Ok);

        result =
            0 != memcmp(settings_Setup87_config, cfg, sizeof(Tfa98xx_Config_t));
        if (result)
                sprintf(lastErrorString, "DSP parameters mismatch");

 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        TRACEOUT;
        return result;
}
/*
 * check battery level to be above 2Volts
 *
 *
 */
int tfa98xxDiagBattery(int slave)
{
        Tfa98xx_handle_t handle;
        int result = 0;         // 1 is failure
        unsigned short reg;

        TRACEIN;
        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 4;

        // enable the clock in bypass mode

        // 48 kHz left channel I2S with coolflux in Bypass
        lastApiError = Tfa98xx_WriteRegister16(handle, TFA98XX_I2SREG, 0x880b); //
        assert(lastApiError == Tfa98xx_Error_Ok);
        //  PLL=BCK, input 1, power off
        lastApiError = Tfa98xx_WriteRegister16(handle, TFA98XX_SYS_CTRL, 0x0219);       //
        assert(lastApiError == Tfa98xx_Error_Ok);
        // 1.0 uF coil, PLL=BCK, input 1, power on
        lastApiError = Tfa98xx_WriteRegister16(handle, TFA98XX_SYS_CTRL, 0x0618);       //
        assert(lastApiError == Tfa98xx_Error_Ok);
        // check if clocks are stable and running
		// give it some time
		usleep(14000); // 14ms good for all rates
        // expect: 0x00 : 0xd85f
        if (tfa98xxDiagStatus
            (handle, 0, TFA98XX_STATUS_PLLS | TFA98XX_STATUS_CLKS)) {
                sprintf(lastErrorString, "clock not running");
                result = 2;     // fail if any of these is clear
                goto stop;
        }
        // check battery level
        lastApiError =
            Tfa98xx_ReadRegister16(handle, TFA98XX_BATTERYVOLTAGE, &reg);
        assert(lastApiError == Tfa98xx_Error_Ok);
        // 2V: 2/(5.5/1024)=372
        if (reg < 372) {
                sprintf(lastErrorString,
                        "battery level too low: exp > 2.0V, rcv=%2.2f",
                        reg * (5.5 / 1024));
                result = 1;
                goto stop;
        }
        // any other errors
        if (tfa98xxDiagStatus
            (handle, TFA98XX_STATUS_ERRORS_SET_MSK,
             TFA98XX_STATUS_ERRORS_CLR_MSK)) {
                sprintf(lastErrorString, "status errorbit active");
                result = 3;
        }
 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        TRACEOUT;
        return result;
}
/*
 * write/read test of a register that has no risk of causing damage
 *   return code:
 *   	2 :  write value wrong
 *
  */
int tfa98xxDiagI2cRw(int slave)
{
        Tfa98xx_handle_t handle;
        int testregoffset, result = 0;      // 1 is failure
        unsigned short testreg;

        TRACEIN;

        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 1;

        // get the index of the testreg
        for ( testregoffset = 0;  testregoffset < MAXREGS;  testregoffset++) {
        	if (regdefs[ testregoffset].offset == RWTEST_REG)
        		break;
        }

        // powerdown to avoid side effects
        lastApiError = Tfa98xx_Powerdown(handle, 1);
        assert(lastApiError == Tfa98xx_Error_Ok);
        // check pwron default first
        lastApiError = Tfa98xx_ReadRegister16(handle, RWTEST_REG, &testreg);    //
        assert(lastApiError == Tfa98xx_Error_Ok);

        if (regdefs[ testregoffset].pwronDefault != (testreg & regdefs[ testregoffset].pwronTestmask)) {
                sprintf(lastErrorString,
                        "poweron default wrong: %s (0x%02x), exp:0x%04x rcv:0x%04x\n",
                        regdefs[ testregoffset].name, regdefs[ testregoffset].offset,
                        regdefs[ testregoffset].pwronDefault, testreg);
                result = 2;
                goto stop;
        }
        // write 0x1234
        lastApiError = Tfa98xx_WriteRegister16(handle, RWTEST_REG, 0x1234);     //
        assert(lastApiError == Tfa98xx_Error_Ok);
        lastApiError = Tfa98xx_ReadRegister16(handle, RWTEST_REG, &testreg);    //
        assert(lastApiError == Tfa98xx_Error_Ok);

        // restore default, else pwrdefault may fail
        lastApiError = Tfa98xx_WriteRegister16(handle, RWTEST_REG, regdefs[RWTEST_REG].pwronDefault);   //
        assert(lastApiError == Tfa98xx_Error_Ok);

        if (0x1234 != testreg) {
                sprintf(lastErrorString,
                        "read back value mismatch: (testreg=0x%02x), exp:0x%04x rcv:0x%04x\n",
                        RWTEST_REG, 0x1234, testreg);
                result = 1;
        }

 stop:
		Tfa98xx_Close(handle);

        lastError = result;
        TRACEOUT;
        return result;
}
static int tfa98xx_codec_remove(struct snd_soc_codec *codec)
{
	enum Tfa98xx_Error err;
	pr_info("%s\n", __func__);

	if (handle_is_open(handles[TOP])) {
		err = Tfa98xx_Close(handles[TOP]);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Top Tfa98xx_Close failed\n", __func__);
		handles[TOP] = -1;
	}
	if (handle_is_open(handles[BOTTOM])) {
		err = Tfa98xx_Close(handles[BOTTOM]);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Top Tfa98xx_Close failed\n", __func__);
		handles[TOP] = -1;
	}
	return 0;
}
/*
 * assume I2S input and verify signal activity
 */
int tfa98xxDiagI2sInput(int slave)
{
        {
                Tfa98xx_handle_t handle;
                int result;
                Tfa98xx_StateInfo_t stateInfo;
                unsigned short sysctrlReg;

                TRACEIN;

                lastApiError = Tfa98xx_Open(slave << 1, &handle);
                if (lastApiError != Tfa98xx_Error_Ok)
                        return 3;

                gHandle = handle; // global prevents reopen
                result = tfa98xxDiagLoadSpeaker(slave);
                if (result) {
                        result = 2;
                        goto stop;
                }
                lastApiError = Tfa98xx_SetConfigured(handle);
                assert(lastApiError == Tfa98xx_Error_Ok);

                //select channel

                lastApiError =
                    Tfa98xx_ReadRegister16(handle, 0x09, &sysctrlReg);
                assert(lastApiError == Tfa98xx_Error_Ok);

                lastApiError = Tfa98xx_WriteRegister16(handle, 0x09, sysctrlReg & ~(0x1 << 13));        // input 1
                //   lastApiError = Tfa98xx_WriteRegister16(handle, 0x09, sysctrlReg | (0x1<<13));  // input 2
                assert(lastApiError == Tfa98xx_Error_Ok);

                lastApiError =
                    Tfa98xx_DspGetStateInfo(handle, &stateInfo);
                assert(lastApiError == Tfa98xx_Error_Ok);

                // check for activity
                if ((stateInfo.statusFlag &
                     (1 << Tfa98xx_SpeakerBoost_Activity)) == 0) {
                        sprintf(lastErrorString, "no audio active on input");
                        result = 1;
                } else
                        result = 0;

 stop:
                Tfa98xx_Close(handle);
                lastError = result;
                gHandle = -1;
                TRACEOUT;
                return result;
        }
}
void read_tfa98xx_id(int *id)
{
	Tfa98xx_handle_t handle;
	int err;
    /* create handle */
    err = Tfa98xx_Open(I2C_ADDRESS, &handle);
    if(err != Tfa98xx_Error_Ok) {
        ALOGE("[%s] Tfa98xx_Open failed! err = %d, I2C_ADDRESS = %#x", __func__, err,I2C_ADDRESS);
    }
	err = Tfa98xx_ReadRegister16(handle, TFA98XX_REVISIONNUMBER, id);
	ALOGD("TFA98xx ID=%#x",*id);
	err = Tfa98xx_Close(handle);
}
/*
 * enable clocks in bypass and verify status
 */
int tfa98xxDiagClock(int slave)
{
        Tfa98xx_handle_t handle;
        int result = 0;         // 1 is failure

        TRACEIN;

        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 3;

        // enable the clock in bypass mode

        // 48 kHz left channel I2S with coolflux in Bypass
        lastApiError = Tfa98xx_WriteRegister16(handle, TFA98XX_I2SREG, 0x880b); //
        assert(lastApiError == Tfa98xx_Error_Ok);
        //  PLL=BCK, input 1, power off
        lastApiError = Tfa98xx_WriteRegister16(handle, TFA98XX_SYS_CTRL, 0x0219);       //
        assert(lastApiError == Tfa98xx_Error_Ok);
        // 1.0 uF coil, PLL=BCK, input 1, power on
        lastApiError = Tfa98xx_WriteRegister16(handle, TFA98XX_SYS_CTRL, 0x0618);       //
        assert(lastApiError == Tfa98xx_Error_Ok);
		// give it some time
		usleep(14000); // 14ms good for all rates
        // check if clocks are stable and running
        // expect: 0x00 : 0xd85f
        if (tfa98xxDiagStatus
            (handle, 0, TFA98XX_STATUS_PLLS | TFA98XX_STATUS_CLKS)) {
                sprintf(lastErrorString, "clock not running");
                result = 1;     // fail if any of these is clear
                goto stop;
        }
        // any other errors
        if (tfa98xxDiagStatus
            (handle, TFA98XX_STATUS_ERRORS_SET_MSK,
             TFA98XX_STATUS_ERRORS_CLR_MSK)) {
                sprintf(lastErrorString, "status errorbit active");
                result = 2;
        }
 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        TRACEOUT;
        return result;
}
/*
 * load speaker parameters and verify readback
 *
 *   note: this function can be called from other tests it uses the global handle
 */
int tfa98xxDiagLoadSpeaker(int slave)
{
        int result = 1;         // 1 is failure
        int gbl=0;
        Tfa98xx_SpeakerParameters_t spkr;

        TRACEIN;

        if ( gHandle<0 ) {
            lastApiError = Tfa98xx_Open(slave << 1, &gHandle);
            if (lastApiError != Tfa98xx_Error_Ok)
                return 2;
        } else
            gbl = 1;

        coldStartup(gHandle);
        lastApiError =
            Tfa98xx_DspWriteSpeakerParameters(gHandle, TFA98XX_SPEAKERPARAMETER_LENGTH,
                                              settings_KS_13X18_DUMBO_speaker);
        assert(lastApiError == Tfa98xx_Error_Ok);

        lastApiError =
            Tfa98xx_DspGetParam(gHandle, 1 /*MODULE_SPEAKERBOOST */ , 0x86,
                                sizeof(spkr), spkr);
        assert(lastApiError == Tfa98xx_Error_Ok);

        result =
            0 != memcmp(settings_KS_13X18_DUMBO_speaker, spkr,
                        sizeof(Tfa98xx_SpeakerParameters_t));
        if (result)
                sprintf(lastErrorString, "DSP parameters mismatch");

 stop:
         if ( !gbl ) {
             Tfa98xx_Close(gHandle);
             lastError = result;
             gHandle=-1;
         }
        TRACEOUT;
        return result;

}
int tfa98xxDiagDsp(int slave)
{
        Tfa98xx_handle_t handle;
        int i, result = 0;      // !0 is failure
        char tag[TFA98XX_MAXTAG], string[TFA98XX_MAXTAG + 1], *ptr;
        const char *exp = DSP_revstring;

        TRACEIN;
        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 3;

        coldStartup(handle);

        lastApiError =
            Tfa98xx_DspGetParam(handle, 1 /*MODULE_SPEAKERBOOST */ , 0xFF,
                                TFA98XX_MAXTAG, tag);
        if (lastApiError != Tfa98xx_Error_Ok) {
                sprintf(lastErrorString, "DSP failure");
                return 1;
        }

        ptr = string;
        // the characters are in every 3rd byte
        for (i = 2; i < TFA98XX_MAXTAG; i += 3) {
                if (isprint(tag[i])) {
                        *ptr++ = tag[i];        // only printable chars
                }
        }
        *ptr = '\0';

        if (strcmp(exp, string)) {
                sprintf(lastErrorString, "wrong DSP revtag: exp %s rcv:%s\n",
                        exp, string);
                return 2;
        }
 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        TRACEOUT;
        return result;
}
/*
 * verify default state of relevant registers
 */
int tfa98xxDiagRegisterDefaults(int slave)
{
        Tfa98xx_handle_t handle;
        int i, result = 0;      // 1 is failure
        unsigned short regval;
        unsigned char reg;

        TRACEIN;

        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 2;

        for (i = 0; i < MAXREGS; i++) {
                if (regdefs[i].pwronTestmask == 0)
                        continue;
                lastApiError =
                    Tfa98xx_ReadRegister16(handle, regdefs[i].offset, &regval);
                assert(lastApiError == Tfa98xx_Error_Ok);

                if (regdefs[i].pwronDefault !=
                    (regval & regdefs[i].pwronTestmask)) {
                        sprintf(lastErrorString,
                                "poweron default wrong: %s (0x%02x), exp:0x%04x rcv:0x%04x\n",
                                regdefs[i].name, regdefs[i].offset,
                                regdefs[i].pwronDefault, regval);
                        result++;
                }
        }
        // set DC-DC peak protection bit
        lastApiError = Tfa98xx_WriteRegister16(handle, TFA98XX_SPKR_CALIBRATION, 0x0c00);       //
        assert(lastApiError == Tfa98xx_Error_Ok);

 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        TRACEOUT;
        return result;
}
/*
 * scan of I2C for ID registers and check for expected device
 *  open the expected device
 */
int tfa98xxDiagI2cScan(int slave)
{
        Tfa98xx_handle_t handle;
        int result = 0;         // 1 is failure

        TRACEIN;

        lastApiError = Tfa98xx_Open(slave << 1, &handle);

        if (lastApiError == Tfa98xx_Error_Ok) {
				Tfa98xx_Close(handle);
        }
        else {
                result = 1;     // non-0 if fail
                sprintf(lastErrorString, "can't find i2c slave 0x%0x", slave);
        }

        lastError = result;
        TRACEOUT;

        return result;
}
/*
 * verify speaker presence by checking the resistance
 */
int tfa98xxDiagSpeakerPresence(int slave)
{
        Tfa98xx_handle_t handle;
        int result;
        float re0;

        TRACEIN;

        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok)
                return 3;

        gHandle = handle;
        result = tfa98xxDiagLoadSpeaker(slave);
        if (result) {
                result = 2;
                goto stop;
        }
        lastApiError = Tfa98xx_SetConfigured(handle);
        assert(lastApiError == Tfa98xx_Error_Ok);
        waitCalibration(handle, &re0);

        // check R for non-0
        if (re0 == 0) {
                sprintf(lastErrorString, "Speaker not detected");
                result = 1;
        } else
                result = 0;

 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        gHandle = -1;
        TRACEOUT;
        return result;
}
/*
 * check status register flags and assume coldstart (or fail)
 *   return code:
 *      1 : error bit
 *   	2 : not cold powered on
 *   	other internal errors
 */
int tfa98xxDiagStatusCold(int slave)
{
        Tfa98xx_handle_t handle;
        int result = 0;         // 1 is failure
        unsigned short statusreg;

        TRACEIN;

        lastApiError = Tfa98xx_Open(slave << 1, &handle);
        if (lastApiError != Tfa98xx_Error_Ok) {
                return 3;
        }

        lastApiError =
            Tfa98xx_ReadRegister16(handle, TFA98XX_STATUSREG, &statusreg);
        assert(lastApiError == Tfa98xx_Error_Ok);

        if (!(statusreg & TFA98XX_STATUS_ACS)) {        /* ensure cold booted */
                sprintf(lastErrorString, "not a cold start");
                result = 2;
                goto stop;
        }

        if (tfa98xxDiagStatus
            (handle, TFA98XX_STATUS_ERRORS_SET_MSK,
             TFA98XX_STATUS_ERRORS_CLR_MSK)) {
                sprintf(lastErrorString, "status errorbit active");
                result = 1;
        }

 stop:
        Tfa98xx_Close(handle);
        lastError = result;
        TRACEOUT;
        return result;
}