/* ** Called by the real-time loop to set the force */ IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_SetSamples(VibeUInt8 nActuatorIndex, VibeUInt16 nOutputSignalBitDepth, VibeUInt16 nBufferSizeInBytes, VibeInt8* pForceOutputBuffer) { #if GUARANTEE_AUTOTUNE_BRAKE_TIME VibeInt8 force = pForceOutputBuffer[0]; if (force > 0 && g_lastForce <= 0) { g_brake = false; ImmVibeSPI_ForceOut_AmpEnable(nActuatorIndex); } else if (force <= 0 && g_lastForce > 0) { g_brake = force < 0; ImmVibeSPI_ForceOut_AmpDisable(nActuatorIndex); } if (g_lastForce != force) { /* AmpDisable sets force to zero, so need to here */ if (force > 0) drv2604_set_rtp_val(pForceOutputBuffer[0]); g_lastForce = force; } #else drv2604_set_rtp_val(pForceOutputBuffer[0]); #endif return VIBE_S_SUCCESS; }
/* ** Called to disable amp (disable output force) */ IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_AmpDisable(VibeUInt8 nActuatorIndex) { if (g_bAmpEnabled) { /* Set the force to 0 */ drv2604_set_rtp_val(0); #if GUARANTEE_AUTOTUNE_BRAKE_TIME /* if a brake signal arrived from daemon, let the chip stay on * extra time to allow it to brake */ if (g_brake && g_workqueue) { queue_delayed_work(g_workqueue, &g_brake_complete, msecs_to_jiffies(AUTOTUNE_BRAKE_TIME)); } else /* disable immediately (smooth effect style) */ #endif { #if USE_DRV2604_STANDBY /* Put hardware in standby via i2c */ drv2604_change_mode(MODE_STANDBY); #endif #if USE_DRV2604_EN_PIN /* Disable hardware via pin */ drv2604_set_en(false); #endif } g_bAmpEnabled = false; } return VIBE_S_SUCCESS; }
static void vibrator_enable(struct timed_output_dev *dev, int value) { #if SUPPORT_TIMED_OUTPUT char mode; hrtimer_cancel(&vibdata.timer); cancel_work_sync(&vibdata.work); #if SUPPORT_WRITE_PAT cancel_work_sync(&vibdata.pat_work); #endif mutex_lock(&vibdata.lock); if (value) { wake_lock(&vibdata.wklock); drv2604_read_reg(STATUS_REG); /* Added by Ken on 20120531 */ if (!g_bAmpEnabled) { mode = drv2604_read_reg(MODE_REG) & DRV2604_MODE_MASK; /* Modified by Ken on 20120530 */ #if DRV2604_USE_RTP_MODE /* Only change the mode if not already in RTP mode; RTP input already set at init */ if (mode != MODE_REAL_TIME_PLAYBACK) { drv2604_change_mode(MODE_REAL_TIME_PLAYBACK); drv2604_set_rtp_val(vibe_strength); vibrator_is_playing = YES; g_bAmpEnabled = true; } #endif #if DRV2604_USE_PWM_MODE /* Only change the mode if not already in PWM mode */ if (mode != MODE_PWM_OR_ANALOG_INPUT) { pwm_duty_enable(vibdata.pwm_dev, 0); drv2604_change_mode(MODE_PWM_OR_ANALOG_INPUT); vibrator_is_playing = YES; g_bAmpEnabled = true; } #endif } if (value > 0) { if (value > MAX_TIMEOUT) value = MAX_TIMEOUT; hrtimer_start(&vibdata.timer, ns_to_ktime((u64)value * NSEC_PER_MSEC), HRTIMER_MODE_REL); } } else vibrator_off(); mutex_unlock(&vibdata.lock); #endif // SUPPORT_TIMED_OUTPUT }
/* ** Called to disable amp (disable output force) */ IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_AmpDisable(VibeUInt8 nActuatorIndex) { if (g_bAmpEnabled) { DbgOut((DBL_VERBOSE, "ImmVibeSPI_ForceOut_AmpDisable.\n")); /* Set the force to 0 */ #if DRV2604_USE_RTP_MODE drv2604_set_rtp_val(0); #endif #if DRV2604_USE_PWM_MODE /* From Xiaomi start */ pwm_duty_enable(vibdata.pwm_dev, 0); /* From Xiaomi end */ #endif /* if a brake signal arrived from daemon, let the chip stay on * extra time to allow it to brake */ if (g_autotune_brake_enabled && g_brake && g_workqueue) { queue_delayed_work(g_workqueue, &g_brake_complete, msecs_to_jiffies(AUTOTUNE_BRAKE_TIME)); } else /* disable immediately (smooth effect style) */ { #if USE_DRV2604_STANDBY /* Put hardware in standby via i2c */ drv2604_change_mode(MODE_STANDBY); #endif #if USE_DRV2604_EN_PIN /* Disable hardware via pin */ drv2604_set_en(false); #endif } g_bAmpEnabled = false; } return VIBE_S_SUCCESS; }
/* ** Called by the real-time loop to set the force */ IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_SetSamples(VibeUInt8 nActuatorIndex, VibeUInt16 nOutputSignalBitDepth, VibeUInt16 nBufferSizeInBytes, VibeInt8* pForceOutputBuffer) { if(g_autotune_brake_enabled) { VibeInt8 force = pForceOutputBuffer[0]; if (force > 0 && g_lastForce <= 0) { g_brake = false; ImmVibeSPI_ForceOut_AmpEnable(nActuatorIndex); } else if (force <= 0 && g_lastForce > 0) { g_brake = force < 0; ImmVibeSPI_ForceOut_AmpDisable(nActuatorIndex); } if (g_lastForce != force) { /* AmpDisable sets force to zero, so need to here */ #if DRV2604_USE_RTP_MODE if (force > 0) drv2604_set_rtp_val(pForceOutputBuffer[0]); #endif #if DRV2604_USE_PWM_MODE /* From Xiaomi start */ /* Xiaomi would like to use the PWM mode to change output level */ u32 uForce; if (pForceOutputBuffer[0] != 0) { uForce = (pForceOutputBuffer[0] > 0)?(pForceOutputBuffer[0]):0; // Added by Ken on 20130530 DbgOut((DBL_VERBOSE, "ImmVibeSPI_ForceOut_SetSamples(%d)\n", uForce)); if (uForce > 126) uForce = 256; else uForce += 128; pwm_duty_enable(vibdata.pwm_dev, uForce); } else { // Added by Ken on 20130530 DbgOut((DBL_VERBOSE, "ImmVibeSPI_ForceOut_SetSamples(0)\n")); pwm_duty_enable(vibdata.pwm_dev, 0); } /* From Xiaomi end */ #endif } g_lastForce = force; } else { #if DRV2604_USE_RTP_MODE drv2604_set_rtp_val(pForceOutputBuffer[0]); #endif #if DRV2604_USE_PWM_MODE /* From Xiaomi start */ /* Xiaomi would like to use the PWM mode to change output level */ u32 uForce; if (pForceOutputBuffer[0] != 0) { uForce = (pForceOutputBuffer[0] > 0) ? (pForceOutputBuffer[0]) : 0; // Added by Ken on 20130530 DbgOut((DBL_VERBOSE, "SetSamples(%d)\n", uForce)); if(uForce > 126) uForce = 256; else uForce += 128; pwm_duty_enable(vibdata.pwm_dev, uForce); } else { // Added by Ken on 20130530 DbgOut((DBL_VERBOSE, "SetSamples(0)\n")); pwm_duty_enable(vibdata.pwm_dev, 0); } /* From Xiaomi end */ #endif } g_bNeedToRestartPlayBack = false; return VIBE_S_SUCCESS; }