blob: 5595ba07e34e5df1dfaebd535168a1b9632583fb [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* include/asm/mach-msm/htc_pwrsink.h
2 *
3 * Copyright (C) 2008 HTC Corporation.
4 * Copyright (C) 2007 Google, Inc.
5 * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17#include <linux/kernel.h>
18#include <linux/platform_device.h>
19#include <linux/err.h>
20#include <linux/hrtimer.h>
21#include <linux/sched.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070022#include <linux/module.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#include "pmic.h"
24#include "timed_output.h"
25
26#include <mach/msm_rpcrouter.h>
27
28#define PM_LIBPROG 0x30000061
29#if (CONFIG_MSM_AMSS_VERSION == 6220) || (CONFIG_MSM_AMSS_VERSION == 6225)
30#define PM_LIBVERS 0xfb837d0b
31#else
32#define PM_LIBVERS 0x10001
33#endif
34
35#define HTC_PROCEDURE_SET_VIB_ON_OFF 21
36#define PMIC_VIBRATOR_LEVEL (3000)
37
38static struct work_struct work_vibrator_on;
39static struct work_struct work_vibrator_off;
40static struct hrtimer vibe_timer;
41
42#ifdef CONFIG_PM8XXX_RPC_VIBRATOR
43static void set_pmic_vibrator(int on)
44{
45 int rc;
46
47 rc = pmic_vib_mot_set_mode(PM_VIB_MOT_MODE__MANUAL);
48 if (rc) {
49 pr_err("%s: Vibrator set mode failed", __func__);
50 return;
51 }
52
53 if (on)
54 rc = pmic_vib_mot_set_volt(PMIC_VIBRATOR_LEVEL);
55 else
56 rc = pmic_vib_mot_set_volt(0);
57
58 if (rc)
59 pr_err("%s: Vibrator set voltage level failed", __func__);
60}
61#else
62static void set_pmic_vibrator(int on)
63{
64 static struct msm_rpc_endpoint *vib_endpoint;
65 struct set_vib_on_off_req {
66 struct rpc_request_hdr hdr;
67 uint32_t data;
68 } req;
69
70 if (!vib_endpoint) {
71 vib_endpoint = msm_rpc_connect(PM_LIBPROG, PM_LIBVERS, 0);
72 if (IS_ERR(vib_endpoint)) {
73 printk(KERN_ERR "init vib rpc failed!\n");
74 vib_endpoint = 0;
75 return;
76 }
77 }
78
79
80 if (on)
81 req.data = cpu_to_be32(PMIC_VIBRATOR_LEVEL);
82 else
83 req.data = cpu_to_be32(0);
84
85 msm_rpc_call(vib_endpoint, HTC_PROCEDURE_SET_VIB_ON_OFF, &req,
86 sizeof(req), 5 * HZ);
87}
88#endif
89
90static void pmic_vibrator_on(struct work_struct *work)
91{
92 set_pmic_vibrator(1);
93}
94
95static void pmic_vibrator_off(struct work_struct *work)
96{
97 set_pmic_vibrator(0);
98}
99
100static void timed_vibrator_on(struct timed_output_dev *sdev)
101{
102 schedule_work(&work_vibrator_on);
103}
104
105static void timed_vibrator_off(struct timed_output_dev *sdev)
106{
107 schedule_work(&work_vibrator_off);
108}
109
110static void vibrator_enable(struct timed_output_dev *dev, int value)
111{
112 hrtimer_cancel(&vibe_timer);
113
114 if (value == 0)
115 timed_vibrator_off(dev);
116 else {
117 value = (value > 15000 ? 15000 : value);
118
119 timed_vibrator_on(dev);
120
121 hrtimer_start(&vibe_timer,
122 ktime_set(value / 1000, (value % 1000) * 1000000),
123 HRTIMER_MODE_REL);
124 }
125}
126
127static int vibrator_get_time(struct timed_output_dev *dev)
128{
129 if (hrtimer_active(&vibe_timer)) {
130 ktime_t r = hrtimer_get_remaining(&vibe_timer);
131 struct timeval t = ktime_to_timeval(r);
132 return t.tv_sec * 1000 + t.tv_usec / 1000;
133 }
134 return 0;
135}
136
137static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
138{
139 timed_vibrator_off(NULL);
140 return HRTIMER_NORESTART;
141}
142
143static struct timed_output_dev pmic_vibrator = {
144 .name = "vibrator",
145 .get_time = vibrator_get_time,
146 .enable = vibrator_enable,
147};
148
149void __init msm_init_pmic_vibrator(void)
150{
151 INIT_WORK(&work_vibrator_on, pmic_vibrator_on);
152 INIT_WORK(&work_vibrator_off, pmic_vibrator_off);
153
154 hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
155 vibe_timer.function = vibrator_timer_func;
156
157 timed_output_dev_register(&pmic_vibrator);
158}
159
160MODULE_DESCRIPTION("timed output pmic vibrator device");
161MODULE_LICENSE("GPL");
162