blob: 35cc4565b38bbebd4ddbc404672d6c16e6637d7e [file] [log] [blame]
Devin Kimba0e9452012-06-21 14:09:34 -07001/*
2** =========================================================================
3** File:
4** ImmVibeSPI.c
5**
6** Description:
7** Device-dependent functions called by Immersion TSP API
8** to control PWM duty cycle, amp enable/disable, save IVT file, etc...
9**
10** Portions Copyright (c) 2008-2010 Immersion Corporation. All Rights Reserved.
11**
12** This file contains Original Code and/or Modifications of Original Code
13** as defined in and that are subject to the GNU Public License v2 -
14** (the 'License'). You may not use this file except in compliance with the
15** License. You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software Foundation, Inc.,
17** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or contact
18** TouchSenseSales@immersion.com.
19**
20** The Original Code and all software distributed under the License are
21** distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22** EXPRESS OR IMPLIED, AND IMMERSION HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23** INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
24** FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see
25** the License for the specific language governing rights and limitations
26** under the License.
27** =========================================================================
28*/
29
30#include <linux/io.h>
31#include <linux/err.h>
32#include <linux/gpio.h>
33#include <linux/regulator/msm-gpio-regulator.h>
34
35#include <mach/irqs.h>
36#include <mach/gpiomux.h>
37#include <mach/msm_iomap.h>
38#include <mach/msm_xo.h>
39
40#ifdef IMMVIBESPIAPI
41#undef IMMVIBESPIAPI
42#endif
43#define IMMVIBESPIAPI static
44
45/*
46** This SPI supports only one actuator.
47*/
48#define NUM_ACTUATORS 1
49
50#define PWM_DUTY_MAX 579 /* 13MHz / (579 + 1) = 22.4kHz */
51
52static bool g_bAmpEnabled = false;
53
54/* gpio and clock control for vibrator */
55
56#define PM8921_GPIO_BASE NR_GPIO_IRQS
57#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
58
59#define REG_WRITEL(value, reg) writel(value, (MSM_CLK_CTL_BASE + reg))
60#define REG_READL(reg) readl((MSM_CLK_CTL_BASE + reg))
61
62#define GPn_MD_REG(n) (0x2D00+32*(n))
63#define GPn_NS_REG(n) (0x2D24+32*(n))
64
65/*
66** This SPI supports only one actuator.
67*/
68#define NUM_ACTUATORS 1
69
70#define PWM_DUTY_MAX 579 /* 13MHz / (579 + 1) = 22.4kHz */
71
72#define GPIO_LIN_MOTOR_EN 33
73#define GPIO_LIN_MOTOR_PWR 47
74#define GPIO_LIN_MOTOR_PWM 3
75
76#define GP_CLK_ID 0 /* gp clk 0 */
77#define GP_CLK_M_DEFAULT 1
78#define GP_CLK_N_DEFAULT 166
79#define GP_CLK_D_MAX GP_CLK_N_DEFAULT
80#define GP_CLK_D_HALF (GP_CLK_N_DEFAULT >> 1)
81
82#define MOTOR_AMP 120
83
84
85static struct gpiomux_setting vibrator_suspend_cfg = {
86 .func = GPIOMUX_FUNC_GPIO,
87 .drv = GPIOMUX_DRV_2MA,
88 .pull = GPIOMUX_PULL_NONE,
89};
90
91static struct gpiomux_setting vibrator_active_cfg_gpio3 = {
92 .func = GPIOMUX_FUNC_2, /*gp_mn:2 */
93 .drv = GPIOMUX_DRV_2MA,
94 .pull = GPIOMUX_PULL_NONE,
95};
96
97static struct msm_gpiomux_config gpio2_vibrator_configs[] = {
98 {
99 .gpio = 3,
100 .settings = {
101 [GPIOMUX_ACTIVE] = &vibrator_active_cfg_gpio3,
102 [GPIOMUX_SUSPENDED] = &vibrator_suspend_cfg,
103 },
104 },
105};
106
107static struct msm_xo_voter *vib_clock;
108static int vibrator_clock_init(void)
109{
110 int rc;
111 /*Vote for XO clock*/
112 vib_clock = msm_xo_get(MSM_XO_TCXO_D0, "vib_clock");
113
114 if (IS_ERR(vib_clock)) {
115 rc = PTR_ERR(vib_clock);
116 printk(KERN_ERR "%s: Couldn't get TCXO_D0 vote for Vib(%d)\n",
117 __func__, rc);
118 }
119 return rc;
120}
121
122static int vibrator_clock_on(void)
123{
124 int rc;
125 rc = msm_xo_mode_vote(vib_clock, MSM_XO_MODE_ON);
126 if (rc < 0) {
127 printk(KERN_ERR "%s: Failed to vote for TCX0_D0 ON (%d)\n",
128 __func__, rc);
129 }
130 return rc;
131}
132
133static int vibrator_clock_off(void)
134{
135 int rc;
136 rc = msm_xo_mode_vote(vib_clock, MSM_XO_MODE_OFF);
137 if (rc < 0) {
138 printk(KERN_ERR "%s: Failed to vote for TCX0_D0 OFF (%d)\n",
139 __func__, rc);
140 }
141 return rc;
142}
143
144static int vibrator_power_set(int enable)
145{
146 int rc = 0;
147 static struct regulator *vreg_l16 = NULL;
148 int enabled = 0;
149
150 if (unlikely(!vreg_l16)) {
151 vreg_l16 = regulator_get(NULL, "8921_l16"); /* 2.6 ~ 3V */
152
153 if (IS_ERR(vreg_l16)) {
154 pr_err("%s: regulator get of 8921_lvs6 failed (%ld)\n",
155 __func__, PTR_ERR(vreg_l16));
156 rc = PTR_ERR(vreg_l16);
157 return rc;
158 }
159 }
160
161 /* fix the unbalanced disables */
162 enabled = regulator_is_enabled(vreg_l16);
163 if (enabled > 0) {
164 if (enable) { /* already enabled */
165 printk("vibrator already enabled\n");
166 return 0;
167 }
168 } else if (enabled == 0) {
169 if (enable == 0) { /* already disabled */
170 printk("vibrator already disabled\n");
171 return 0;
172 }
173 } else { /* (enabled < 0) */
174 pr_warn("%s: regulator_is_enabled failed\n", __func__);
175 }
176
177 //rc = regulator_set_voltage(vreg_l16, 3000000, 3000000);
178 rc = regulator_set_voltage(vreg_l16, 2800000, 2800000);
179
180 if(enable) {
181 printk("vibrator_power_set() : vibrator enable\n");
182 rc = regulator_enable(vreg_l16);
183 }
184 else {
185 printk("vibrator_power_set() : vibrator disable\n");
186 rc = regulator_disable(vreg_l16);
187 }
188
189 return rc;
190}
191
192static void vibrator_pwm_set(int enable, int amp, int n_value)
193{
194 uint M_VAL = GP_CLK_M_DEFAULT;
195 uint D_VAL = GP_CLK_D_MAX;
196 uint D_INV = 0; /* QCT support invert bit for msm8960 */
197
198 if (enable) {
199 vibrator_clock_on();
200
201 D_VAL = (((GP_CLK_D_MAX -1) * amp) >> 8) + GP_CLK_D_HALF;
202
203 if (D_VAL > GP_CLK_D_HALF) {
204 if (D_VAL == GP_CLK_D_MAX) /* Max duty is 99% */
205 D_VAL = 2;
206 else
207 D_VAL = GP_CLK_D_MAX - D_VAL;
208
209 D_INV = 1;
210 }
211
212 REG_WRITEL(
213 (((M_VAL & 0xffU) << 16U) + /* M_VAL[23:16] */
214 ((~(D_VAL << 1)) & 0xffU)), /* D_VAL[7:0] */
215 GPn_MD_REG(GP_CLK_ID));
216
217 REG_WRITEL(
218 ((((~(n_value-M_VAL)) & 0xffU) << 16U) + /* N_VAL[23:16] */
219 (1U << 11U) + /* CLK_ROOT_ENA[11] : Enable(1) */
220 ((D_INV & 0x01U) << 10U) +/* CLK_INV[10] : Disable(0) */
221 (1U << 9U) + /* CLK_BRANCH_ENA[9] : Enable(1) */
222 (1U << 8U) + /* NMCNTR_EN[8] : Enable(1) */
223 (0U << 7U) + /* MNCNTR_RST[7] : Not Active(0) */
224 (2U << 5U) + /* MNCNTR_MODE[6:5] : Dual-edge mode(2) */
225 (3U << 3U) + /* PRE_DIV_SEL[4:3] : Div-4 (3) */
226 (5U << 0U)), /* SRC_SEL[2:0] : CXO (5) */
227 GPn_NS_REG(GP_CLK_ID));
228 }
229 else {
230 vibrator_clock_off();
231
232 REG_WRITEL(
233 ((((~(n_value-M_VAL)) & 0xffU) << 16U) + /* N_VAL[23:16] */
234 (0U << 11U) + /* CLK_ROOT_ENA[11] : Disable(0) */
235 (0U << 10U) + /* CLK_INV[10] : Disable(0) */
236 (0U << 9U) + /* CLK_BRANCH_ENA[9] : Disable(0) */
237 (0U << 8U) + /* NMCNTR_EN[8] : Disable(0) */
238 (0U << 7U) + /* MNCNTR_RST[7] : Not Active(0) */
239 (2U << 5U) + /* MNCNTR_MODE[6:5] : Dual-edge mode(2) */
240 (3U << 3U) + /* PRE_DIV_SEL[4:3] : Div-4 (3) */
241 (5U << 0U)), /* SRC_SEL[2:0] : CXO (5) */
242 GPn_NS_REG(GP_CLK_ID));
243 }
244}
245
246static void vibrator_ic_enable_set(int enable)
247{
248 int gpio_lin_motor_en = 0;
249 gpio_lin_motor_en = PM8921_GPIO_PM_TO_SYS(GPIO_LIN_MOTOR_EN);
250
251 if (enable)
252 gpio_direction_output(gpio_lin_motor_en, 1);
253 else
254 gpio_direction_output(gpio_lin_motor_en, 0);
255}
256
257/*
258** Called to disable amp (disable output force)
259*/
260IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_AmpDisable(VibeUInt8 nActuatorIndex)
261{
262
263 if (g_bAmpEnabled) {
264 DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_AmpDisable.\n"));
265
266 g_bAmpEnabled = false;
267
268 vibrator_ic_enable_set(0);
269 vibrator_pwm_set(0, 0, GP_CLK_N_DEFAULT);
270 vibrator_power_set(0);
271 }
272
273 return VIBE_S_SUCCESS;
274}
275
276/*
277** Called to enable amp (enable output force)
278*/
279IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_AmpEnable(VibeUInt8 nActuatorIndex)
280{
281
282 if (!g_bAmpEnabled) {
283 DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_AmpEnable.\n"));
284
285 g_bAmpEnabled = true;
286
287 vibrator_power_set(1);
288 vibrator_pwm_set(1, 0, GP_CLK_N_DEFAULT);
289 vibrator_ic_enable_set(1);
290 }
291 else {
292 DbgOut((KERN_DEBUG "[ImmVibeSPI] : ImmVibeSPI_ForceOut_AmpEnable [%d]\n", g_bAmpEnabled ));
293 }
294
295 return VIBE_S_SUCCESS;
296}
297
298/*
299** Called at initialization time to set PWM freq, disable amp, etc...
300*/
301IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_Initialize(void)
302{
303 int rc;
304 int gpio_motor_en = 0;
305 int gpio_motor_pwm = 0;
306
307 DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_Initialize.\n"));
308
309 /* to force ImmVibeSPI_ForceOut_AmpDisable disabling the amp */
310 g_bAmpEnabled = true;
311
312 /*
313 ** Disable amp.
314 ** If multiple actuators are supported, please make sure to call
315 ** ImmVibeSPI_ForceOut_AmpDisable for each actuator (provide the actuator index as
316 ** input argument).
317 */
318
319 gpio_motor_en = GPIO_LIN_MOTOR_EN;
320 gpio_motor_pwm = GPIO_LIN_MOTOR_PWM;
321
322 /* GPIO function setting */
323 msm_gpiomux_install(gpio2_vibrator_configs, ARRAY_SIZE(gpio2_vibrator_configs));
324
325 /* GPIO setting for Motor EN in pmic8921 */
326 gpio_motor_en = PM8921_GPIO_PM_TO_SYS(GPIO_LIN_MOTOR_EN);
327 rc = gpio_request(gpio_motor_en, "lin_motor_en");
328
329 if (rc) {
330 DbgOut(("GPIO_LIN_MOTOR_EN %d request failed\n", gpio_motor_en));
331 return -1;
332 }
333
334 /* gpio init */
335 rc = gpio_request(gpio_motor_pwm, "lin_motor_pwm");
336
337 if (unlikely(rc < 0))
338 DbgOut(("not able to get gpio\n"));
339
340 vibrator_clock_init();
341
342 ImmVibeSPI_ForceOut_AmpDisable(0);
343
344 return VIBE_S_SUCCESS;
345}
346
347/*
348** Called at termination time to set PWM freq, disable amp, etc...
349*/
350IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_Terminate(void)
351{
352
353 DbgOut((KERN_DEBUG "ImmVibeSPI_ForceOut_Terminate.\n"));
354
355 /*
356 ** Disable amp.
357 ** If multiple actuators are supported, please make sure to call
358 ** ImmVibeSPI_ForceOut_AmpDisable for each actuator (provide the actuator index as
359 ** input argument).
360 */
361 ImmVibeSPI_ForceOut_AmpDisable(0);
362
363 return VIBE_S_SUCCESS;
364}
365
366/*
367** Called by the real-time loop to set PWM duty cycle
368*/
369IMMVIBESPIAPI VibeStatus ImmVibeSPI_ForceOut_SetSamples(VibeUInt8 nActuatorIndex, VibeUInt16 nOutputSignalBitDepth, VibeUInt16 nBufferSizeInBytes, VibeInt8* pForceOutputBuffer)
370{
371 VibeInt8 nForce;
372
373 switch (nOutputSignalBitDepth) {
374 case 8:
375 /* pForceOutputBuffer is expected to contain 1 byte */
376 if (nBufferSizeInBytes != 1)
377 return VIBE_E_FAIL;
378
379 nForce = pForceOutputBuffer[0];
380 break;
381 case 16:
382 /* pForceOutputBuffer is expected to contain 2 byte */
383 if (nBufferSizeInBytes != 2)
384 return VIBE_E_FAIL;
385
386 /* Map 16-bit value to 8-bit */
387 nForce = ((VibeInt16*)pForceOutputBuffer)[0] >> 8;
388 break;
389 default:
390 /* Unexpected bit depth */
391 return VIBE_E_FAIL;
392 }
393 /* Check the Force value with Max and Min force value */
394
395 if (nForce > 127)
396 nForce = 127;
397 if (nForce < -127)
398 nForce = -127;
399
400 vibrator_pwm_set(1, nForce, GP_CLK_N_DEFAULT);
401
402 return VIBE_S_SUCCESS;
403}
404
405/*
406** Called to get the device name (device name must be returned as ANSI char)
407*/
408IMMVIBESPIAPI VibeStatus ImmVibeSPI_Device_GetName(VibeUInt8 nActuatorIndex, char *szDevName, int nSize)
409{
410#if 0
411 /* The following code is provided as a sample.
412 * Please modify as required.
413 */
414
415 if ((!szDevName) || (nSize < 1))
416 return VIBE_E_FAIL;
417
418 DbgOut((KERN_DEBUG "ImmVibeSPI_Device_GetName.\n"));
419
420 strncpy(szDevName, "Generic Linux Device", nSize-1);
421 /* make sure the string is NULL terminated */
422 szDevName[nSize - 1] = '\0';
423#endif
424
425 return VIBE_S_SUCCESS;
426}