blob: 94d5c42789e1e8b4a307968f563cc07627f3c89c [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>
22#include "pmic.h"
23#include "timed_output.h"
24
25#include <mach/msm_rpcrouter.h>
26
27#define PM_LIBPROG 0x30000061
28#if (CONFIG_MSM_AMSS_VERSION == 6220) || (CONFIG_MSM_AMSS_VERSION == 6225)
29#define PM_LIBVERS 0xfb837d0b
30#else
31#define PM_LIBVERS 0x10001
32#endif
33
34#define HTC_PROCEDURE_SET_VIB_ON_OFF 21
35#define PMIC_VIBRATOR_LEVEL (3000)
36
37static struct work_struct work_vibrator_on;
38static struct work_struct work_vibrator_off;
39static struct hrtimer vibe_timer;
40
41#ifdef CONFIG_PM8XXX_RPC_VIBRATOR
42static void set_pmic_vibrator(int on)
43{
44 int rc;
45
46 rc = pmic_vib_mot_set_mode(PM_VIB_MOT_MODE__MANUAL);
47 if (rc) {
48 pr_err("%s: Vibrator set mode failed", __func__);
49 return;
50 }
51
52 if (on)
53 rc = pmic_vib_mot_set_volt(PMIC_VIBRATOR_LEVEL);
54 else
55 rc = pmic_vib_mot_set_volt(0);
56
57 if (rc)
58 pr_err("%s: Vibrator set voltage level failed", __func__);
59}
60#else
61static void set_pmic_vibrator(int on)
62{
63 static struct msm_rpc_endpoint *vib_endpoint;
64 struct set_vib_on_off_req {
65 struct rpc_request_hdr hdr;
66 uint32_t data;
67 } req;
68
69 if (!vib_endpoint) {
70 vib_endpoint = msm_rpc_connect(PM_LIBPROG, PM_LIBVERS, 0);
71 if (IS_ERR(vib_endpoint)) {
72 printk(KERN_ERR "init vib rpc failed!\n");
73 vib_endpoint = 0;
74 return;
75 }
76 }
77
78
79 if (on)
80 req.data = cpu_to_be32(PMIC_VIBRATOR_LEVEL);
81 else
82 req.data = cpu_to_be32(0);
83
84 msm_rpc_call(vib_endpoint, HTC_PROCEDURE_SET_VIB_ON_OFF, &req,
85 sizeof(req), 5 * HZ);
86}
87#endif
88
89static void pmic_vibrator_on(struct work_struct *work)
90{
91 set_pmic_vibrator(1);
92}
93
94static void pmic_vibrator_off(struct work_struct *work)
95{
96 set_pmic_vibrator(0);
97}
98
99static void timed_vibrator_on(struct timed_output_dev *sdev)
100{
101 schedule_work(&work_vibrator_on);
102}
103
104static void timed_vibrator_off(struct timed_output_dev *sdev)
105{
106 schedule_work(&work_vibrator_off);
107}
108
109static void vibrator_enable(struct timed_output_dev *dev, int value)
110{
111 hrtimer_cancel(&vibe_timer);
112
113 if (value == 0)
114 timed_vibrator_off(dev);
115 else {
116 value = (value > 15000 ? 15000 : value);
117
118 timed_vibrator_on(dev);
119
120 hrtimer_start(&vibe_timer,
121 ktime_set(value / 1000, (value % 1000) * 1000000),
122 HRTIMER_MODE_REL);
123 }
124}
125
126static int vibrator_get_time(struct timed_output_dev *dev)
127{
128 if (hrtimer_active(&vibe_timer)) {
129 ktime_t r = hrtimer_get_remaining(&vibe_timer);
130 struct timeval t = ktime_to_timeval(r);
131 return t.tv_sec * 1000 + t.tv_usec / 1000;
132 }
133 return 0;
134}
135
136static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
137{
138 timed_vibrator_off(NULL);
139 return HRTIMER_NORESTART;
140}
141
142static struct timed_output_dev pmic_vibrator = {
143 .name = "vibrator",
144 .get_time = vibrator_get_time,
145 .enable = vibrator_enable,
146};
147
148void __init msm_init_pmic_vibrator(void)
149{
150 INIT_WORK(&work_vibrator_on, pmic_vibrator_on);
151 INIT_WORK(&work_vibrator_off, pmic_vibrator_off);
152
153 hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
154 vibe_timer.function = vibrator_timer_func;
155
156 timed_output_dev_register(&pmic_vibrator);
157}
158
159MODULE_DESCRIPTION("timed output pmic vibrator device");
160MODULE_LICENSE("GPL");
161