aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/motor
diff options
context:
space:
mode:
authorAndrew Dodd <atd7@cornell.edu>2012-09-22 11:52:26 -0400
committerGerrit Code Review <gerrit@review.cyanogenmod.com>2012-09-23 07:54:02 -0400
commit25c3e5a976c5efb34410fb4d41e41a291525c1fe (patch)
tree15f75b544327873da160f556e6d92cacac0fa74d /drivers/motor
parentfc40e40a40effd3eb74527474384c297e90d54f8 (diff)
downloadkernel_samsung_smdk4412-25c3e5a976c5efb34410fb4d41e41a291525c1fe.zip
kernel_samsung_smdk4412-25c3e5a976c5efb34410fb4d41e41a291525c1fe.tar.gz
kernel_samsung_smdk4412-25c3e5a976c5efb34410fb4d41e41a291525c1fe.tar.bz2
tspdrv: Add missing ISA1200 file
Change-Id: I9cb91cbbdfd19f8f4c4246c3ff4f3ecb60378ded
Diffstat (limited to 'drivers/motor')
-rw-r--r--drivers/motor/ImmVibeSPI_isa1200.c561
1 files changed, 561 insertions, 0 deletions
diff --git a/drivers/motor/ImmVibeSPI_isa1200.c b/drivers/motor/ImmVibeSPI_isa1200.c
new file mode 100644
index 0000000..42c36b5
--- /dev/null
+++ b/drivers/motor/ImmVibeSPI_isa1200.c
@@ -0,0 +1,561 @@
+/*
+** =========================================================================
+** File:
+** ImmVibeSPI.c
+**
+** Description:
+** Device-dependent functions called by Immersion TSP API
+** to control PWM duty cycle, amp enable/disable, save IVT file, etc...
+**
+** Portions Copyright (c) 2008-2010 Immersion Corporation. All Rights Reserved.
+**
+** This file contains Original Code and/or Modifications of Original Code
+** as defined in and that are subject to the GNU Public License v2 -
+** (the 'License'). You may not use this file except in compliance with the
+** License. You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or contact
+** TouchSenseSales@immersion.com.
+**
+** The Original Code and all software distributed under the License are
+** distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+** EXPRESS OR IMPLIED, AND IMMERSION HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+** INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
+** FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see
+** the License for the specific language governing rights and limitations
+** under the License.
+** =========================================================================
+*/
+
+#ifdef IMMVIBESPIAPI
+#undef IMMVIBESPIAPI
+#endif
+#define IMMVIBESPIAPI static
+
+#include <linux/isa1200_vibrator.h>
+
+/*
+** This SPI supports only one actuator.
+*/
+#define NUM_ACTUATORS 1
+
+#define ISA1200_I2C_ADDRESS 0x90
+#define SCTRL (0)
+#define HCTRL0 (0x30)
+#define HCTRL1 (0x31)
+#define HCTRL2 (0x32)
+#define HCTRL3 (0x33)
+#define HCTRL4 (0x34)
+#define HCTRL5 (0x35)
+#define HCTRL6 (0x36)
+#define HCTRL7 (0x37)
+#define HCTRL8 (0x38)
+#define HCTRL9 (0x39)
+#define HCTRLA (0x3A)
+#define HCTRLB (0x3B)
+#define HCTRLC (0x3C)
+#define HCTRLD (0x3D)
+
+#define LDO_VOLTAGE_23V 0x08
+#define LDO_VOLTAGE_24V 0x09
+#define LDO_VOLTAGE_25V 0x0A
+#define LDO_VOLTAGE_26V 0x0B
+#define LDO_VOLTAGE_27V 0x0C
+#define LDO_VOLTAGE_28V 0x0D
+#define LDO_VOLTAGE_29V 0x0E
+#define LDO_VOLTAGE_30V 0x0F
+#define LDO_VOLTAGE_31V 0x00
+#define LDO_VOLTAGE_32V 0x01
+#define LDO_VOLTAGE_33V 0x02
+#define LDO_VOLTAGE_34V 0x03
+#define LDO_VOLTAGE_35V 0x04
+#define LDO_VOLTAGE_36V 0x05
+#define LDO_VOLTAGE_37V 0x06
+#define LDO_VOLTAGE_38V 0x07
+
+static bool g_bAmpEnabled;
+
+/* Variable defined to allow for tuning of the handset. */
+/* For temporary section for Tuning Work */
+#if 0
+#define VIBETONZ_TUNING
+#define ISA1200_GEN_MODE
+#endif
+#define MOTOR_TYPE_LRA
+
+#ifdef VIBETONZ_TUNING
+extern VibeStatus ImmVibeGetDeviceKernelParameter(VibeInt32 nDeviceIndex, VibeInt32 nDeviceKernelParamID, VibeInt32 *pnDeviceKernelParamValue);
+#endif /* VIBETONZ_TUNING */
+
+/* PWM mode selection */
+#ifndef ISA1200_GEN_MODE
+#define ISA1200_PWM_MODE
+#if 0
+#define ISA1200_PWM_256DIV_MODE
+#else
+#define ISA1200_PWM_128DIV_MODE
+#endif
+#endif
+
+/* Actuator selection */
+#ifndef MOTOR_TYPE_LRA
+#define MOTOR_TYPE_ERM
+#endif
+
+#define ISA1200_HEN_ENABLE
+#define RETRY_CNT 10
+
+#define SYS_API_LEN_HIGH vibtonz_chip_enable(true)
+#define SYS_API_LEN_LOW vibtonz_chip_enable(false)
+#define SYS_API_HEN_HIGH
+#define SYS_API_HEN_LOW
+#define SYS_API_VDDP_ON
+#define SYS_API_VDDP_OFF
+#define SYS_API__I2C__Write( _addr, _dataLength, _data) \
+ vibtonz_i2c_write(_addr, _dataLength, _data)
+#define SLEEP(_us_time)
+
+#define PWM_CLK_ENABLE vibtonz_clk_enable(true)
+#define PWM_CLK_DISABLE vibtonz_clk_enable(false)
+
+#define DEBUG_MSG(fmt, ...) \
+ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+
+#define SYS_API_SET_PWM_FREQ(freq)
+#define SYS_API_SET_PWM_DUTY(ratio) vibtonz_clk_config(ratio)
+
+#ifdef ISA1200_GEN_MODE
+#define PWM_PLLDIV_DEFAULT 0x02
+#define PWM_FREQ_DEFAULT 0x00
+#define PWM_PERIOD_DEFAULT 0x74
+#define PWM_DUTY_DEFAULT 0x3a
+VibeUInt32 g_nPWM_PLLDiv = PWM_PLLDIV_DEFAULT;
+VibeUInt32 g_nPWM_Freq = PWM_FREQ_DEFAULT;
+VibeUInt32 g_nPWM_Period = PWM_PERIOD_DEFAULT;
+VibeUInt32 g_nPWM_Duty = PWM_DUTY_DEFAULT;
+#else
+#ifdef ISA1200_PWM_256DIV_MODE
+#define PWM_PERIOD_DEFAULT 44800
+#else
+#define PWM_PERIOD_DEFAULT 22400
+#endif
+VibeUInt32 g_nPWM_Freq = PWM_PERIOD_DEFAULT;
+#endif
+
+#define LDO_VOLTAGE_DEFAULT LDO_VOLTAGE_30V
+VibeUInt32 g_nLDO_Voltage = LDO_VOLTAGE_DEFAULT;
+
+#define DEVICE_NAME "Generic"
+
+/*
+** Called to disable amp (disable output force)
+*/
+IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_AmpDisable(VibeUInt8 nActuatorIndex)
+{
+ int cnt = 0;
+ unsigned char I2C_data[2];
+ int ret = VIBE_S_SUCCESS;
+
+ if (g_bAmpEnabled)
+ {
+ DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_AmpDisable.\n"));
+
+ g_bAmpEnabled = false;
+
+
+#ifdef ISA1200_HEN_ENABLE
+ SYS_API_HEN_LOW;
+#endif
+
+ I2C_data[1] = 0x00; // Haptic drive disable
+ I2C_data[0]= HCTRL0;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpDisable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", HCTRL0, ret);
+
+ PWM_CLK_DISABLE;
+ }
+
+ return VIBE_S_SUCCESS;
+}
+
+/*
+** Called to enable amp (enable output force)
+*/
+IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_AmpEnable(VibeUInt8 nActuatorIndex)
+{
+ int cnt = 0;
+ unsigned char I2C_data[2];
+ int ret = VIBE_S_SUCCESS;
+#ifdef VIBETONZ_TUNING
+ VibeUInt32 nPWM_PLLDiv_KernelParam = 0;
+ VibeUInt32 nPWM_Freq_KernelParam = 0;
+ VibeUInt32 nPWM_Period_KernelParam = 0;
+ VibeUInt32 nPWM_Duty_KernelParam = 0;
+ VibeUInt32 nPWM_Update_KernelParam = 0;
+#endif
+
+ if (!g_bAmpEnabled)
+ {
+ DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_AmpEnable.\n"));
+ g_bAmpEnabled = true;
+
+#ifdef VIBETONZ_TUNING /* For Resonant Frequency Test */
+ ImmVibeGetDeviceKernelParameter(0, 85, &nPWM_PLLDiv_KernelParam); /* use for PLL variable */
+ ImmVibeGetDeviceKernelParameter(0, 86, &nPWM_Freq_KernelParam); /* use for Freq variable */
+ ImmVibeGetDeviceKernelParameter(0, 87, &nPWM_Period_KernelParam); /* use for Period variable */
+ ImmVibeGetDeviceKernelParameter(0, 88, &nPWM_Duty_KernelParam); /* use for Duty variable */
+ ImmVibeGetDeviceKernelParameter(0, 89, &nPWM_Update_KernelParam); /* use for Update variable */
+
+ /* Update current Period and Duty values if those from the Kernel Parameters table are acceptables (value != 0) */
+#ifdef ISA1200_GEN_MODE
+ if(nPWM_Update_KernelParam)
+ {
+ g_nPWM_PLLDiv = nPWM_PLLDiv_KernelParam;
+ g_nPWM_Freq = nPWM_Freq_KernelParam;
+ g_nPWM_Period = nPWM_Period_KernelParam;
+ g_nPWM_Duty = nPWM_Duty_KernelParam;
+
+#ifdef MOTOR_TYPE_LRA
+ I2C_data[1] = 0xC0 ; // EXT clock + DAC inversion + LRA
+#else
+ I2C_data[1] = 0xE0; // EXT clock + DAC inversion + ERM
+#endif
+ I2C_data[0]= HCTRL1;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpEnable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = 0x00 ; // Disable Software Reset
+ I2C_data[0]= HCTRL2;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpEnable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = 0x03 + ( g_nPWM_PLLDiv<<4); // PLLLDIV
+ I2C_data[0]= HCTRL3;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpEnable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = g_nPWM_Freq; // PWM control
+ I2C_data[0]= HCTRL4;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpEnable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = g_nPWM_Duty; // PWM High Duty
+ I2C_data[0]= HCTRL5;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpEnable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = g_nPWM_Period; // PWM Period
+ I2C_data[0]= HCTRL6;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpEnable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+ }
+#else
+ if(nPWM_Update_KernelParam)
+ {
+ g_nPWM_Freq = nPWM_Freq_KernelParam;
+ }
+ SYS_API_SET_PWM_FREQ(g_nPWM_Freq); // 22.4Khz
+ SYS_API_SET_PWM_DUTY(500); // 50% Duty Cycle, 1000 ~ 0
+#endif
+#endif /* VIBETONZ_TUNING */
+
+ PWM_CLK_ENABLE;
+
+#ifdef ISA1200_HEN_ENABLE
+ SYS_API_HEN_HIGH;
+#endif
+
+#ifdef ISA1200_GEN_MODE
+ I2C_data[1] = 0x91; //Haptic Enable + PWM generation mode
+#else
+#ifdef ISA1200_PWM_256DIV_MODE
+ I2C_data[1] = 0x89; // Haptic Drive Disable + PWM Input mode + 44.8Khz mode
+#else
+ I2C_data[1] = 0x88; // Haptic Drive Disable + PWM Input mode + 22.4Khz mode
+#endif
+#endif
+ I2C_data[0]= HCTRL0;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_AmpEnable] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ }
+
+ return VIBE_S_SUCCESS;
+}
+
+/*
+** Called at initialization time to set PWM frequencies, disable amp, etc...
+*/
+IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_Initialize(void)
+{
+ int cnt = 0;
+ unsigned char I2C_data[2];
+ int ret = VIBE_S_SUCCESS;
+
+ DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_Initialize.\n"));
+
+ SYS_API_VDDP_ON;
+ SYS_API_LEN_HIGH;
+
+ SLEEP(200 /*us*/);
+
+ I2C_data[1] = g_nLDO_Voltage; // LDO Voltage
+ I2C_data[0]= SCTRL;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+#ifdef ISA1200_GEN_MODE
+ I2C_data[1] = 0x11; //Haptic Drive Disable + PWM generation mode + 44.8Khz mode
+ I2C_data[0]= HCTRL0;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+#ifdef MOTOR_TYPE_LRA
+ I2C_data[1] = 0xC0 ; // EXT clock + DAC inversion + LRA
+#else
+ I2C_data[1] = 0xE0; // EXT clock + DAC inversion + ERM
+#endif
+ I2C_data[0]= HCTRL1;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = 0x00 ; // Disable Software Reset
+ I2C_data[0]= HCTRL2;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = 0x03 + ( g_nPWM_PLLDiv<<4); // PLLLDIV
+ I2C_data[0]= HCTRL3;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = g_nPWM_Freq; // PWM control
+ I2C_data[0]= HCTRL4;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = g_nPWM_Duty; // PWM High Duty
+ I2C_data[0]= HCTRL5;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = g_nPWM_Period; // PWM Period
+ I2C_data[0]= HCTRL6;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+#else // PWM Input Mode
+
+#ifdef ISA1200_PWM_256DIV_MODE
+ I2C_data[1] = 0x09; // Haptic Drive Disable + PWM Input mode + 44.8Khz mode
+#else
+ I2C_data[1] = 0x08; // Haptic Drive Disable + PWM Input mode + 22.4Khz mode
+#endif
+ I2C_data[0]= HCTRL0;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+#ifdef MOTOR_TYPE_LRA
+ I2C_data[1] = 0x43; // EXT clock + DAC inversion + LRA
+#else
+ I2C_data[1] = 0x63; // EXT clock + DAC inversion + ERM
+#endif
+ I2C_data[0]= HCTRL1;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = 0x00; // Disable Software Reset
+ I2C_data[0]= HCTRL2;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+
+ I2C_data[1] = 0x00; // Default
+ I2C_data[0]= HCTRL4;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Initialize] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+#endif
+ return VIBE_S_SUCCESS;
+}
+
+/*
+** Called at termination time to set PWM freq, disable amp, etc...
+*/
+IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_Terminate(void)
+{
+ DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_Terminate.\n"));
+ SYS_API_LEN_LOW;
+#ifdef ISA1200_HEN_ENABLE
+ SYS_API_HEN_LOW;
+#endif
+ SYS_API_VDDP_OFF;
+ return VIBE_S_SUCCESS;
+}
+
+/*
+** Called by the real-time loop to set PWM_MAG duty cycle
+*/
+IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_SetSamples(VibeUInt8 nActuatorIndex, VibeUInt16 nOutputSignalBitDepth, VibeUInt16 nBufferSizeInBytes, VibeInt8* pForceOutputBuffer)
+{
+ VibeInt8 nForce;
+ int cnt = 0;
+ unsigned char I2C_data[2];
+ int ret = VIBE_S_SUCCESS;
+
+ switch (nOutputSignalBitDepth)
+ {
+ case 8:
+ /* pForceOutputBuffer is expected to contain 1 byte */
+ if (nBufferSizeInBytes != 1)
+ {
+ DbgOut((KERN_ERR "[ImmVibeSPI] ImmVibeSPI_ForceOut_SetSamples nBufferSizeInBytes = %d \n", nBufferSizeInBytes ));
+ return VIBE_E_FAIL;
+ }
+ nForce = pForceOutputBuffer[0];
+ break;
+ case 16:
+ /* pForceOutputBuffer is expected to contain 2 byte */
+ if (nBufferSizeInBytes != 2) return VIBE_E_FAIL;
+
+ /* Map 16-bit value to 8-bit */
+ nForce = ((VibeInt16*)pForceOutputBuffer)[0] >> 8;
+ break;
+ default:
+ /* Unexpected bit depth */
+ return VIBE_E_FAIL;
+ }
+
+ if(nForce == 0)
+ {
+#ifdef ISA1200_GEN_MODE
+ I2C_data[1] = g_nPWM_Duty; // PWM High Duty 50%
+ I2C_data[0]= HCTRL5;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Set] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+#else
+ SYS_API_SET_PWM_DUTY(500); //50%
+#endif
+ if (g_bAmpEnabled == true)
+ {
+ ImmVibeSPI_ForceOut_AmpDisable(0);
+ }
+ }
+ else
+ {
+ if (g_bAmpEnabled != true)
+ {
+ ImmVibeSPI_ForceOut_AmpEnable(0);
+ }
+#ifdef ISA1200_GEN_MODE
+ I2C_data[1] = g_nPWM_Duty + ((g_nPWM_Duty-1)*nForce)/127;
+ I2C_data[0]= HCTRL5;
+ do
+ {
+ ret = SYS_API__I2C__Write(ISA1200_I2C_ADDRESS, 2 /* data length*/, I2C_data);
+ cnt++;
+ }while(VIBE_S_SUCCESS != ret && cnt < RETRY_CNT);
+ if( VIBE_S_SUCCESS != ret) DEBUG_MSG("[ImmVibeSPI_ForceOut_Set] I2C_Write Error, Slave Address = [%d], ret = [%d]\n", I2C_data[0], ret);
+#else
+ SYS_API_SET_PWM_DUTY(500 - (490 * nForce)/127);
+#endif
+ }
+ return VIBE_S_SUCCESS;
+}
+/*
+** Called to set force output frequency parameters
+*/
+IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_SetFrequency(VibeUInt8 nActuatorIndex, VibeUInt16 nFrequencyParameterID, VibeUInt32 nFrequencyParameterValue)
+{
+ return VIBE_S_SUCCESS;
+}
+
+/*
+** Called to get the device name (device name must be returned as ANSI char)
+*/
+IMMVIBESPIAPI VibeStatus ImmVibeSPI_Device_GetName(VibeUInt8 nActuatorIndex, char *szDevName, int nSize)
+{
+ return VIBE_S_SUCCESS;
+}