/*
 * Tfa9890_DspSystemStable will compensate for the wrong behavior of CLKS
 * to determine if the DSP subsystem is ready for patch and config loading.
 *
 * A MTP calibration register is checked for non-zero.
 *
 * Note: This only works after i2c reset as this will clear the MTP contents.
 * When we are configured then the DSP communication will synchronize access.
 *
 */
enum Tfa98xx_Error Tfa9890_DspSystemStable(Tfa98xx_handle_t handle, int *ready)
{
	enum Tfa98xx_Error error;
	unsigned short status, mtp0;
	int tries;

	/* check the contents of the STATUS register */
	error = Tfa98xx_ReadRegister16(handle, TFA98XX_STATUSREG, &status);
	if (error)
		goto errorExit;

	/* if AMPS is set then we were already configured and running
	 *   no need to check further
	 */
	*ready = (status & TFA98XX_STATUSREG_AMPS_MSK)
	    == (TFA98XX_STATUSREG_AMPS_MSK);
	if (*ready)		/* if  ready go back */
		return error;	/* will be Tfa98xx_Error_Ok */

	/* check AREFS and CLKS: not ready if either is clear */
	*ready =
	    (status &
	     (TFA98XX_STATUSREG_AREFS_MSK | TFA98XX_STATUSREG_CLKS_MSK))
	    == (TFA98XX_STATUSREG_AREFS_MSK | TFA98XX_STATUSREG_CLKS_MSK);
	if (!*ready)		/* if not ready go back */
		return error;	/* will be Tfa98xx_Error_Ok */

	/* check MTPB
	 *   mtpbusy will be active when the subsys copies MTP to I2C
	 *   2 times retry avoids catching this short mtpbusy active period
	 */
	for (tries = 2; tries > 0; tries--) {
		error =
		    Tfa98xx_ReadRegister16(handle, TFA98XX_STATUSREG, &status);
		if (error)
			goto errorExit;
		/* check the contents of the STATUS register */
		*ready = (status & TFA98XX_STATUSREG_MTPB_MSK) == 0;
		if (*ready)	/* if ready go on */
			break;
	}
	if (tries == 0)		/* ready will be 0 if retries exausted */
		return Tfa98xx_Error_Ok;

	/* check the contents of  MTP register for non-zero,
	 *  this indicates that the subsys is ready  */
	error = Tfa98xx_ReadRegister16(handle, 0x84, &mtp0);
	if (error)
		goto errorExit;

	*ready = (mtp0 != 0);	/* The MTP register written? */

	return error;

errorExit:
	*ready = 0;
	_ASSERT(error);		/* an error here can be considered
				   to be fatal */
	return error;
}
Ejemplo n.º 2
0
Tfa98xx_Error_t Tfa9890_DspReset(Tfa98xx_handle_t handle, int state)
{
	Tfa98xx_Error_t error;
	unsigned short value49, value;

	/* for TFA9890 temporarily disable clock gating when dsp reset is used */
	error = Tfa98xx_ReadRegister16(handle, TFA98XX_CURRENTSENSE4, &value49);
	if (error) return error;

	if (Tfa98xx_Error_Ok == error) {
		/* clock gating off */
		value = value49 | TFA98XX_CURRENTSENSE4_CTRL_CLKGATECFOFF; // set the bit
		error = Tfa98xx_WriteRegister16(handle, TFA98XX_CURRENTSENSE4, value);
		if (error) return error;
	}

	error = Tfa98xx_ReadRegister16(handle, TFA98XX_CF_CONTROLS, &value);
	if (error) return error;

	/* set requested the DSP reset signal state */
	value = state ? (value |  TFA98XX_CF_CONTROLS_RST_MSK) :
			(value & ~TFA98XX_CF_CONTROLS_RST_MSK);

	error = Tfa98xx_WriteRegister16(handle, TFA98XX_CF_CONTROLS,
			value);

	/* clock gating restore */
	error = Tfa98xx_WriteRegister16(handle, 0x49, value49);/* clock gating restore */
	return error;
}
Ejemplo n.º 3
0
/*
 * 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;
}
Ejemplo n.º 4
0
static void waitCalibration(Tfa98xx_handle_t handle, int *calibrateDone)
{
	enum Tfa98xx_Error err;
	int tries = 0;
	unsigned short mtp;
	unsigned short spkrCalibration;
#define WAIT_TRIES 1000

	err = Tfa98xx_ReadRegister16(handle, TFA98XX_MTP, &mtp);

	/* in case of calibrate once wait for MTPEX */
	if (mtp & TFA98XX_MTP_MTPOTC) {
		while ((*calibrateDone == 0) && (tries < WAIT_TRIES)) {
			err = Tfa98xx_ReadRegister16(handle,
				TFA98XX_MTP, &mtp);
			/* check MTP bit1 (MTPEX) */
			*calibrateDone = (mtp & TFA98XX_MTP_MTPEX);
			tries++;
		}
	} else { /* poll xmem for calibrate always */
		while ((*calibrateDone == 0) && (tries < WAIT_TRIES)) {
			/* TODO optimise with wait estimation */
			err = Tfa98xx_DspReadMem(handle, 231, 1,
				calibrateDone);
			tries++;
		}
		if (tries == WAIT_TRIES)
			pr_err("%s: calibrateDone 231 timedout\n", __func__);
	}

	err = Tfa98xx_ReadRegister16(handle,
		TFA98XX_SPKR_CALIBRATION, &spkrCalibration);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
			__func__, err);
		return;
	}

	spkrCalibration &= ~(TFA98XX_SPKR_CALIBRATION_TROS_MSK);

	err = Tfa98xx_WriteRegister16(handle,
		TFA98XX_SPKR_CALIBRATION, spkrCalibration);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_WriteRegister16 failed %d\n",
			__func__, err);
		return;
	}
}
Ejemplo n.º 5
0
/*
 * 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;
}
Ejemplo n.º 6
0
static void change_stereo_speaker_lr(int speaker_lr)
{
	enum Tfa98xx_Error err;
	unsigned int h;
	unsigned short status = 0;
	int timeout;

	pr_info("%s\n", __func__);
	for (h = 0; h < 2; h++) {
		err = Tfa98xx_SetMute(handles[h], Tfa98xx_Mute_Amplifier);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Tfa98xx_SetMute failed, h=%d\n",
				__func__, h);
		msleep(33);

		err = Tfa98xx_ReadRegister16(
			handles[h], TFA98XX_STATUSREG, &status);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Tfa98xx_ReadRegister16 failed, h=%d\n",
				__func__, h);
		timeout = 0;
		while ((status & TFA98XX_STATUSREG_SWS_MSK)
			== TFA98XX_STATUSREG_SWS_MSK) {
			err = Tfa98xx_ReadRegister16(handles[h],
				TFA98XX_STATUSREG, &status);
			if (err != Tfa98xx_Error_Ok)
				pr_err("%s: Tfa98xx_ReadRegister16 failed,"\
					" h=%d\n", __func__, h);
				timeout++;
			if (timeout > 50) {
				pr_info("%s timeout SWS checking:%d\n",
					__func__, status);
				break;
			}
		}
	}

	set_speaker_lr(handles, speaker_lr);

	for (h = 0; h < 2; h++) {
		err = Tfa98xx_SetMute(handles[h], Tfa98xx_Mute_Off);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Tfa98xx_SetMute failed, h=%d\n",
				__func__, h);
	}
	speaker_lr_now = speaker_lr;
}
Ejemplo n.º 7
0
static void stereo_speaker_off(void)
{
	enum Tfa98xx_Error err;
	unsigned int h;
	unsigned short status = 0;
	int timeout;

	pr_info("%s\n", __func__);
	for (h = 0; h < 2; h++) {
		err = Tfa98xx_SetMute(handles[h], Tfa98xx_Mute_Amplifier);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Tfa98xx_SetMute failed, h=%d\n",
				__func__, h);
		msleep(33);

	/* NXP SL: Added checking if amplifier is still switching or not
		to avoid pop sound */
	/* now wait for the amplifier to turn off */
	err = Tfa98xx_ReadRegister16(
			handles[h], TFA98XX_STATUSREG, &status);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Tfa98xx_ReadRegister16 failed, h=%d\n",
				__func__, h);
		timeout = 0;
		while ((status & TFA98XX_STATUSREG_SWS_MSK)
			== TFA98XX_STATUSREG_SWS_MSK) {
			err = Tfa98xx_ReadRegister16(handles[h],
				TFA98XX_STATUSREG, &status);
			if (err != Tfa98xx_Error_Ok)
				pr_err("%s: Tfa98xx_ReadRegister16 failed,"\
					" h=%d\n", __func__, h);
				timeout++;
			if (timeout > 50) {
				pr_info("%s timeout SWS checking:%d\n",
					__func__, status);
				break;
			}
		}

		err = Tfa98xx_Powerdown(handles[h], 1);
		if (err != Tfa98xx_Error_Ok)
			pr_err("%s: Tfa98xx_Powerdown failed, h=%d\n",
				__func__, h);
	}
}
Ejemplo n.º 8
0
/*
 * 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;
}
Ejemplo n.º 9
0
Tfa98xx_Error_t Tfa9890_specific(Tfa98xx_handle_t handle)
{
	    Tfa98xx_Error_t error = Tfa98xx_Error_Ok;
        unsigned short value;

        ALOGD("[%s][%s] 2", __FILE__, __func__);
        if (!handle_is_open(handle))
                return Tfa98xx_Error_NotOpen;

        /* reset all i2C registers to default */
        error = Tfa98xx_WriteRegister16(handle, 0x09, 0x0002);

        if (Tfa98xx_Error_Ok == error) {
                error = Tfa98xx_ReadRegister16(handle, 0x09, &value);
        }
        if (Tfa98xx_Error_Ok == error) {
                /* DSP must be in control of the amplifier to avoid plops */
                value |= TFA98XX_SYS_CTRL_AMPE_POS;
                error = Tfa98xx_WriteRegister16(handle, 0x09, value);
        }

        /* some other registers must be set for optimal amplifier behaviour */

        if (Tfa98xx_Error_Ok == error) {
				error = Tfa98xx_WriteRegister16(handle, 0x06, 0x000F); // not for n1c
		}
        if (Tfa98xx_Error_Ok == error) {
				error = Tfa98xx_WriteRegister16(handle, 0x07, 0x8FFF); // not for n1c
		}
		if (Tfa98xx_Error_Ok == error) {
				error = Tfa98xx_WriteRegister16(handle, 0x08, 0x7832); // change for n1c
        }
        if (Tfa98xx_Error_Ok == error) {
                error = Tfa98xx_WriteRegister16(handle, 0x09, 0x824D);
        }
        if (Tfa98xx_Error_Ok == error) {
        		error = Tfa98xx_WriteRegister16(handle, 0x0A, 0x38E5); // not for n1c
		}
        if (Tfa98xx_Error_Ok == error) {
                error = Tfa98xx_WriteRegister16(handle, 0x0E, 0x0F01);// not for n1c
		}

        if (Tfa98xx_Error_Ok == error) {
                error = Tfa98xx_WriteRegister16(handle, 0x46, 0x4000);// not for n1c
        }
        if (Tfa98xx_Error_Ok == error) {
				error = Tfa98xx_WriteRegister16(handle, 0x47, 0x5901);
		}
        if (Tfa98xx_Error_Ok == error) {
				error = Tfa98xx_WriteRegister16(handle, 0x48, 0x06C0);  
		}
		if (Tfa98xx_Error_Ok == error) {
				error = Tfa98xx_WriteRegister16(handle, 0x49, 0xAD93);
        }

        return error;
}
Ejemplo n.º 10
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;
        }
}
Ejemplo n.º 11
0
/*
 * Unbypassed the DSP
 */
static int tfa98xx_unbypass_dsp(Tfa98xx_handle_t handleIn)
{
	enum Tfa98xx_Error err = Tfa98xx_Error_Other;
	unsigned short i2SRead = 0;
	unsigned short sysRead = 0;
	unsigned short sysCtrlRead = 0;
	unsigned short batProtRead = 0;

	if (handleIn == -1)
		return err;

	/* basic settings for quickset */
	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_I2SREG, &i2SRead);
	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_I2S_SEL_REG, &sysRead);
	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_SYS_CTRL, &sysCtrlRead);
	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_BAT_PROT, &batProtRead);

	i2SRead |= TFA98XX_I2SREG_CHSA; /* Set CHSA to Unbypass DSP */
	sysRead |= TFA9890_I2S_SEL_REG_POR;/* Set I2S SEL REG to set
					DCDC compensation to default 100%*/
	sysRead &= ~(TFA98XX_I2S_SEL_REG_SPKR_MSK);/*Set impedance to be
							defined by DSP */
	sysCtrlRead |= TFA98XX_SYS_CTRL_DCA_MSK;/* Set DCDC to active mode*/
	sysCtrlRead |= TFA98XX_SYS_CTRL_CFE_MSK;/* Enable Coolflux */

	batProtRead &= ~(TFA989X_BAT_PROT_BSSBY_MSK);/*Set clipper active */

	/* Set CHSA to Unbypass DSP */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_I2SREG, i2SRead);
	/* Set I2S SEL REG to set DCDC compensation to default 100% and
	Set impedance to be defined by DSP */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_I2S_SEL_REG, sysRead);
	/* Set DCDC to active mode and enable Coolflux */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_SYS_CTRL, sysCtrlRead);
	/* Set bypass clipper battery protection */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_BAT_PROT, batProtRead);

	return err;
}
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);
}
Ejemplo n.º 13
0
/*
 * Bypass DSP handling
 */
static int tfa98xx_bypass_dsp(Tfa98xx_handle_t handleIn)
{
	enum Tfa98xx_Error err = Tfa98xx_Error_Other;
	unsigned short i2SRead = 0;
	unsigned short sysRead = 0;
	unsigned short sysCtrlRead = 0;
	unsigned short batProtRead = 0;


	if (handleIn == -1)
		return err;

	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_I2SREG, &i2SRead);
	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_I2S_SEL_REG, &sysRead);
	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_SYS_CTRL, &sysCtrlRead);
	err = Tfa98xx_ReadRegister16(handleIn, TFA98XX_BAT_PROT, &batProtRead);

	i2SRead &= ~(TFA98XX_I2SREG_CHSA_MSK); /* Set CHSA to bypass DSP */
	sysRead &= ~(TFA98XX_I2S_SEL_REG_DCFG_MSK);/* Set DCDC compensation to
							off */
	sysRead |= TFA98XX_I2S_SEL_REG_SPKR_MSK; /* Set impedance as 8ohm */
	sysCtrlRead &= ~(TFA98XX_SYS_CTRL_DCA_MSK);/* Set DCDC to follower
							mode */
	sysCtrlRead &= ~(TFA98XX_SYS_CTRL_CFE_MSK);/* Disable coolflux */

	batProtRead |= TFA989X_BAT_PROT_BSSBY_MSK;/* Set clipper bypassed */

	/* Set CHSA to bypass DSP */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_I2SREG, i2SRead);
	/* Set DCDC compensation to off and set impedance as 8ohm */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_I2S_SEL_REG, sysRead);
	/* Set DCDC to follower mode and disable coolflux  */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_SYS_CTRL, sysCtrlRead);
	/* Set bypass clipper battery protection */
	err = Tfa98xx_WriteRegister16(handleIn, TFA98XX_BAT_PROT, batProtRead);

	return err;
}
Ejemplo n.º 14
0
static int checkMTPEX(Tfa98xx_handle_t handle)
{
	unsigned short mtp;
	enum Tfa98xx_Error err;
	err = Tfa98xx_ReadRegister16(handle, TFA98XX_MTP, &mtp);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
			__func__, err);
	}

	if (mtp & (1<<1))  /* check MTP bit1 (MTPEX) */
		return 1;   /* MTPEX is 1, calibration is done */
	else
		return 0;   /* MTPEX is 0, calibration is not done yet */
}
Ejemplo n.º 15
0
/*
 * check status register flags for any of the error bits set
 *  return 0 if ok
 *  	   1 if not ok
 *  	   other internal errors
 */
int tfa98xxDiagStatus(Tfa98xx_handle_t handle, unsigned short setmask,
                      unsigned short clearmask)
{
        int result = 0;         // 1 is failure
        unsigned short statusreg;

        TRACEIN;

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

        if ((statusreg & setmask))      /* check for any of these bits set */
                return 1;
        if ((~statusreg & clearmask))   /* check for any of these bits clear */
                return 1;

        lastError = result;
        TRACEOUT;
        return result;
}
Ejemplo n.º 16
0
/*
 * 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;
}
Ejemplo n.º 17
0
/*
 * 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;
}
Ejemplo n.º 18
0
static int tfa98xx_enable(void)
{
	int ret = 0;
	enum Tfa98xx_Error err;
	unsigned short status1 = 0;
	unsigned short status2 = 0;
	bool cold_start = false;
	struct tfa98xx_param_data *preset_ptr[2] = {NULL, NULL};
	struct tfa98xx_param_data *config_ptr[2] = {NULL, NULL};
	struct tfa98xx_param_data *speaker_ptr[2] = {NULL, NULL};
	struct tfa98xx_param_data *eq_ptr[2] = {NULL, NULL};

	if (speaker_type >= 0
		&& speaker_type <= SPEAKER_TYPE_VOICECALL
		&& speaker_channel >= 0
		&& speaker_channel <= SPEAKER_CHANNEL_BOTH
		&& speaker_lr >= 0
		&& speaker_lr <= SPEAKER_LR_SWAP)
		pr_info("%s type:%s channel:%s lr:%s\n",
			__func__,
			speaker_type_text[speaker_type],
			speaker_channel_text[speaker_channel],
			speaker_lr_text[speaker_lr]);
	else
		pr_info("%s type:%d channel:%d lr:%d\n",
			__func__, speaker_type, speaker_channel, speaker_lr);

	if (speaker_type_now != speaker_type
		|| speaker_channel_now != speaker_channel) {
		tfa98xx_disable();
		cold_start = true;
	}
	speaker_ptr[TOP] = &speaker_data[AMP_TOP];
	speaker_ptr[BOTTOM] = &speaker_data[AMP_BOTTOM];
	config_ptr[TOP] = &config_data[AMP_TOP];
	config_ptr[BOTTOM] = &config_data[AMP_BOTTOM];
	if (speaker_type >= 0 && speaker_type < SPEAKER_TYPE_MAX) {
		preset_ptr[TOP] = preset_data_table[speaker_type][TOP];
		preset_ptr[BOTTOM] = preset_data_table[speaker_type][BOTTOM];
		eq_ptr[TOP] = eql_data_table[speaker_type][TOP];
		eq_ptr[BOTTOM] = eql_data_table[speaker_type][BOTTOM];
	} else {
		pr_err("%s: Invalid speaker type:%x", __func__, speaker_type);
		return -EINVAL;
	}

	if (speaker_bypass_dsp == SPEAKER_BYPASS_DSP_ON) {
		if (speaker_channel == SPEAKER_CHANNEL_TOP
		 || speaker_channel == SPEAKER_CHANNEL_BOTH) {
			err = bypass_dsp_speaker_on(TOP);
			if (err != Tfa98xx_Error_Ok) {
				pr_err("%s: bypass_speaker_on failed %d\n",
					__func__, err);
			}
		}
		if (speaker_channel == SPEAKER_CHANNEL_BOTTOM
		 || speaker_channel == SPEAKER_CHANNEL_BOTH) {
			err = bypass_dsp_speaker_on(BOTTOM);
			if (err != Tfa98xx_Error_Ok) {
				pr_err("%s: bypass_speaker_on failed %d\n",
					__func__, err);
			}
		}

	} else if (speaker_channel == SPEAKER_CHANNEL_TOP) {
		if (preset_ptr[TOP] == NULL) {
			pr_err("%s: Invalid speaker type:%x channel:%d",
				__func__, speaker_type, speaker_channel);
			return -EINVAL;
		}
		err = Tfa98xx_ReadRegister16(
			handles[TOP], TFA98XX_STATUSREG, &status1);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
				__func__, err);
		}
		if (cold_start || (status1 & TFA98XX_STATUSREG_ACS_MSK) != 0) {
			pr_info("cold start %04x\n", status1);
			ret = mono_speaker_on(
				TOP,
				speaker_ptr[TOP],
				config_ptr[TOP],
				preset_ptr[TOP],
				eq_ptr[TOP]);
		} else {
			pr_info("warm start %04x\n", status1);
			ret = mono_speaker_warm_on(TOP);
		}

	} else if (speaker_channel == SPEAKER_CHANNEL_BOTTOM) {
		if (preset_ptr[BOTTOM] == NULL) {
			pr_err("%s: Invalid speaker type:%x channel:%d",
				__func__, speaker_type, speaker_channel);
			return -EINVAL;
		}
		err = Tfa98xx_ReadRegister16(
			handles[BOTTOM], TFA98XX_STATUSREG, &status1);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
				__func__, err);
		}
		if (cold_start || (status1 & TFA98XX_STATUSREG_ACS_MSK) != 0) {
			pr_info("cold start %04x\n", status1);
			ret = mono_speaker_on(
				BOTTOM,
				speaker_ptr[BOTTOM],
				config_ptr[BOTTOM],
				preset_ptr[BOTTOM],
				eq_ptr[BOTTOM]);
		} else {
			pr_info("warm start %04x\n", status1);
			ret = mono_speaker_warm_on(BOTTOM);
		}

	} else if (speaker_channel == SPEAKER_CHANNEL_BOTH) {
		if (preset_ptr[TOP] == NULL || preset_ptr[BOTTOM] == NULL) {
			pr_err("%s: Invalid speaker type:%x channel:%d",
				__func__, speaker_type, speaker_channel);
			return -EINVAL;
		}
		err = Tfa98xx_ReadRegister16(
			handles[TOP], TFA98XX_STATUSREG, &status1);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
				__func__, err);
		}
		err = Tfa98xx_ReadRegister16(
			handles[BOTTOM], TFA98XX_STATUSREG, &status2);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
				__func__, err);
		}
		if (cold_start
			|| (status1 & TFA98XX_STATUSREG_ACS_MSK) != 0
			|| (status2 & TFA98XX_STATUSREG_ACS_MSK) != 0) {
			pr_info("cold start %04x %04x\n", status1, status2);
			ret = stereo_speaker_on(
				speaker_ptr,
				config_ptr,
				preset_ptr,
				eq_ptr);
		} else if (speaker_lr != speaker_lr_now) {
			pr_info("speaker LR change %d\n", speaker_lr);
			ret = set_speaker_lr(handles, speaker_lr);
			ret = stereo_speaker_warm_on();
		} else {
			pr_info("warm start %04x %04x\n", status1, status2);
			ret = stereo_speaker_warm_on();
		}
	}
	speaker_type_now = speaker_type;
	speaker_channel_now = speaker_channel;
	speaker_lr_now = speaker_lr;
	speaker_bypass_dsp_now = speaker_bypass_dsp;
	speaker_synced_now = speaker_synced;

	return ret;
}
Ejemplo n.º 19
0
static void coldStartup(Tfa98xx_handle_t handle)
{
	enum Tfa98xx_Error err;
	unsigned short status;
	int ready = 0;
	int timeout;
	unsigned short dcdcRead = 0;
	unsigned short dcdcBoost = 0;

	/* load the optimal TFA98xx in HW settings */
	err = Tfa98xx_Init(handle);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_Init failed %d\n", __func__, err);
		return;
	}

	/* NXP SL: Sample rate should be set before power up */
	/* Set sample rate to example 48000*/
	err = Tfa98xx_SetSampleRate(handle, SAMPLE_RATE);
	if (err != Tfa98xx_Error_Ok)
		pr_err("%s: Tfa98xx_SetSampleRate failed %d\n", __func__, err);

	/* Power On the device by setting bit 0 to 0 of register 9*/
	err = Tfa98xx_Powerdown(handle, 0);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_Powerdown failed %d\n", __func__, err);
		return;
	}

	/* set Max boost coil current 1.92 A */
	err = Tfa98xx_ReadRegister16(handle, TFA98XX_DCDCBOOST, &dcdcRead);
	dcdcRead &= ~(TFA98XX_DCDCBOOST_DCMCC_MSK);
	dcdcRead |= (3 << TFA98XX_DCDCBOOST_DCMCC_POS);
	err = Tfa98xx_WriteRegister16(handle, TFA98XX_DCDCBOOST, dcdcRead);

	/* set Max boost voltage 7.5 V */
	err = Tfa98xx_ReadRegister16(handle, TFA98XX_DCDCBOOST, &dcdcBoost);
	dcdcBoost &= ~(TFA98XX_DCDCBOOST_DCVO_MSK);
	dcdcBoost |= 3;
	err = Tfa98xx_WriteRegister16(handle, TFA98XX_DCDCBOOST, dcdcBoost);

	/* Check the PLL is powered up from status register 0*/
	err = Tfa98xx_ReadRegister16(handle, TFA98XX_STATUSREG, &status);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
			__func__, err);
		return;
	}
	timeout = 0;
	while ((status & TFA98XX_STATUSREG_AREFS_MSK) == 0) {
		/* not ok yet */
		err = Tfa98xx_ReadRegister16(handle, TFA98XX_STATUSREG,
			&status);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
				__func__, err);
			return;
		}
		msleep(20);
		timeout++;
		if (timeout > 50) {
			pr_info("%s timeout status:%x\n", __func__, status);
			break;
		}
	}

	/*  powered on
	 *    - now it is allowed to access DSP specifics
	 *    - stall DSP by setting reset
	 * */
	err = Tfa98xx_DspReset(handle, 1);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_DspReset failed %d\n", __func__, err);
		return;
	}

	/*  wait until the DSP subsystem hardware is ready
	 *    note that the DSP CPU is not running yet (RST=1)
	 * */
	timeout = 0;
	while (ready == 0) {
		/* are we ready? */
		err = Tfa98xx_DspSystemStable(handle, &ready);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_DspSystemStable failed %d\n",
				__func__, err);
			return;
		}
		msleep(20);
		timeout++;
		if (timeout > 50) {
			pr_info("%s timeout ready:%d\n", __func__, ready);
			break;
		}
	}

   /* Load cold-boot patch for the first time to force cold start-up.
    *  use the patchload only to write the internal register
    * */
	dspPatch(handle, &patch_data[PATCH_COLDBOOT]);

	err = Tfa98xx_ReadRegister16(handle, TFA98XX_STATUSREG, &status);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
			__func__, err);
		return;
	}

	if ((status & TFA98XX_STATUSREG_ACS_MSK) == 0) {
		pr_err("%s: status & TFA98XX_STATUSREG_ACS_MSK == 0\n",
			__func__);
		return;
	}

	/* cold boot, need to load all parameters and patches */
	/* patch the ROM code */
	dspPatch(handle, &patch_data[PATCH_DSP]);
}
Ejemplo n.º 20
0
static void setOtc(Tfa98xx_handle_t handle, int otcOn)
{
	enum Tfa98xx_Error err;
	unsigned short mtp;
	unsigned short status;
	unsigned short spkrCalibration;
	int mtpChanged = 0;
	int timeout;

	err = Tfa98xx_ReadRegister16(handle,
		TFA98XX_SPKR_CALIBRATION, &spkrCalibration);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
			__func__, err);
		return;
	}

	spkrCalibration |= TFA98XX_SPKR_CALIBRATION_TROS_MSK;
	spkrCalibration &= ~(TFA98XX_SPKR_CALIBRATION_EXTTS_MSK);
	spkrCalibration |= (SPKR_CALIBRATION_EXTTS_VALUE
		<< TFA98XX_SPKR_CALIBRATION_EXTTS_POS);

	err = Tfa98xx_WriteRegister16(handle,
		TFA98XX_SPKR_CALIBRATION, spkrCalibration);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_WriteRegister16 failed %d\n",
			__func__, err);
		return;
	}

	err = Tfa98xx_ReadRegister16(handle, TFA98XX_MTP, &mtp);
	if (err != Tfa98xx_Error_Ok) {
		pr_err("%s: Tfa98xx_DspReset failed %d\n", __func__, err);
		return;
	}

	if ((otcOn != 0) && (otcOn != 1)) {
		pr_err("%s: Tfa98xx_ReadRegister16 failed %d\n",
			__func__, err);
		return;
	}

	/* set reset MTPEX bit if needed */
	if ((mtp & TFA98XX_MTP_MTPOTC) != otcOn) {
		/* need to change the OTC bit, set MTPEX=0 in any case */
		/* unlock key2 */
		err = Tfa98xx_WriteRegister16(handle, 0x0B, 0x5A);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_DspReset failed %d\n",
				__func__, err);
			return;
		}

		/* MTPOTC=otcOn, MTPEX=0 */
		err = Tfa98xx_WriteRegister16(handle, TFA98XX_MTP,
			(unsigned short)otcOn);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_DspReset failed %d\n",
				__func__, err);
			return;
		}

		/* CIMTP=1 */
		err = Tfa98xx_WriteRegister16(handle, 0x62, 1<<11);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_DspReset failed %d\n",
				__func__, err);
			return;
		}

		mtpChanged = 1;

	}

	timeout = 0;
	do {
		msleep(20);
		err = Tfa98xx_ReadRegister16(handle,
			TFA98XX_STATUSREG, &status);
		pr_info("%s %04x\n", __func__, status);
		if (err != Tfa98xx_Error_Ok) {
			pr_err("%s: Tfa98xx_DspReset failed %d\n",
				__func__, err);
			return;
		}
		timeout++;
		if (timeout > 50) {
			pr_info("%s timeout\n", __func__);
			break;
		}
	} while ((status & TFA98XX_STATUSREG_MTPB_MSK)
		== TFA98XX_STATUSREG_MTPB_MSK);

}