blob: d36058042a2c8cd6a9b834b692fac432f10f8ffc [file] [log] [blame]
Umang Agrawalc1fc0772017-12-19 12:06:49 +05301/* Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
Matthew Qine8b71a42015-06-26 17:12:32 +08002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <spmi.h>
30#include <platform/iomap.h>
31#include <pm_vib.h>
Wufeng Jiang1ce072f2015-08-06 19:07:09 +080032#include <target.h>
33#include <vibrator.h>
Umang Agrawal6df58d72019-05-22 12:06:07 +053034#include <smem.h>
Matthew Qine8b71a42015-06-26 17:12:32 +080035
Umang Agrawal6df58d72019-05-22 12:06:07 +053036#define HAPTIC_BASE(s_id) (s_id ? (PMI_SECOND_SLAVE_ADDR_BASE + 0xC000):((PMI_SECOND_SLAVE_OFFSET << 16) + 0xC000))
37#define QPNP_HAP_EN_CTL_REG(s_id) (HAPTIC_BASE(s_id) + 0x46)
38#define QPNP_HAP_EN_CTL2_REG(s_id) (HAPTIC_BASE(s_id) + 0x48)
39#define QPNP_HAP_ACT_TYPE_REG(s_id) (HAPTIC_BASE(s_id) + 0x4C)
40#define QPNP_HAP_WAV_SHAPE_REG(s_id) (HAPTIC_BASE(s_id) + 0x4D)
41#define QPNP_HAP_PLAY_MODE_REG(s_id) (HAPTIC_BASE(s_id) + 0x4E)
42#define QPNP_HAP_LRA_AUTO_RES_REG(s_id) (HAPTIC_BASE(s_id) + 0x4F)
43#define QPNP_HAP_VMAX_REG(s_id) (HAPTIC_BASE(s_id) + 0x51)
44#define QPNP_HAP_ILIM_REG(s_id) (HAPTIC_BASE(s_id) + 0x52)
45#define QPNP_HAP_SC_DEB_REG(s_id) (HAPTIC_BASE(s_id) + 0x53)
46#define QPNP_HAP_RATE_CFG1_REG(s_id) (HAPTIC_BASE(s_id) + 0x54)
47#define QPNP_HAP_RATE_CFG2_REG(s_id) (HAPTIC_BASE(s_id) + 0x55)
48#define QPNP_HAP_INT_PWM_REG(s_id) (HAPTIC_BASE(s_id) + 0x56)
49#define QPNP_HAP_PWM_CAP_REG(s_id) (HAPTIC_BASE(s_id) + 0x58)
50#define QPNP_HAP_BRAKE_REG(s_id) (HAPTIC_BASE(s_id) + 0x5C)
51#define QPNP_HAP_PLAY_REG(s_id) (HAPTIC_BASE(s_id) + 0x70)
Matthew Qine8b71a42015-06-26 17:12:32 +080052
53#define QPNP_HAP_ACT_TYPE_MASK 0x01
54#define QPNP_HAP_PLAY_MODE_MASK 0x3F
55#define QPNP_HAP_DIRECT 0x0
56#define QPNP_HAP_VMAX_MASK 0x3F
57#define QPNP_HAP_VMAX 0x22
58#define QPNP_HAP_ILIM_MASK 0x01
59#define QPNP_HAP_ILIM 0x01
60#define QPNP_HAP_SC_DEB_MASK 0x07
61#define QPNP_HAP_SC_DEB_8CLK 0x01
62#define QPNP_HAP_INT_PWM_MASK 0x03
63#define QPNP_HAP_INT_PWM_505KHZ 0x01
64#define QPNP_HAP_WAV_SHAPE_MASK 0x01
65#define QPNP_HAP_WAV_SHAPE_SQUARE 0x01
66#define QPNP_HAP_PWM_CAP_MASK 0x03
67#define QPNP_HAP_PWM_CAP_13PF 0x01
68#define QPNP_HAP_RATE_CFG1_MASK 0xFF
Matthew Qine8b71a42015-06-26 17:12:32 +080069#define QPNP_HAP_RATE_CFG2_MASK 0x0F
Matthew Qine8b71a42015-06-26 17:12:32 +080070#define QPNP_HAP_EN_BRAKE_EN_MASK 0x01
71#define QPNP_HAP_EN_BRAKING_EN 0x01
72#define QPNP_HAP_BRAKE_VMAX_MASK 0xFF
73#define QPNP_HAP_BRAKE_VMAX 0xF
74#define QPNP_HAP_ERM 0x1
Wufeng Jiang1ce072f2015-08-06 19:07:09 +080075#define QPNP_HAP_LRA 0x0
Matthew Qine8b71a42015-06-26 17:12:32 +080076#define QPNP_HAP_PLAY_MASK 0x80
77#define QPNP_HAP_PLAY_EN 0x80
78#define QPNP_HAP_MASK 0x80
79#define QPNP_HAP_EN 0x80
80#define QPNP_HAP_PLAY_DIS 0x00
81#define QPNP_HAP_DIS 0x00
82#define QPNP_HAP_BRAKE_MASK 0xFE
83#define QPNP_HAP_LRA_AUTO_DISABLE 0x00
84#define QPNP_HAP_LRA_AUTO_MASK 0x70
85
86/* Turn on vibrator */
Umang Agrawalc1fc0772017-12-19 12:06:49 +053087void pm_haptic_vib_turn_on(void)
Matthew Qine8b71a42015-06-26 17:12:32 +080088{
Parth Dixit7f683712015-12-23 15:59:16 +053089 struct qpnp_hap vib_config = {0};
Umang Agrawal6df58d72019-05-22 12:06:07 +053090 uint32_t pmic = target_get_pmic();
91 uint32_t slave_id = 1;
Parth Dixit7f683712015-12-23 15:59:16 +053092
Umang Agrawal6df58d72019-05-22 12:06:07 +053093 if(!target_is_pmi_enabled() && (pmic != PMIC_IS_PM660))
Parth Dixit550ddf32016-11-28 17:00:29 +053094 return;
95
Umang Agrawal6df58d72019-05-22 12:06:07 +053096 if (pmic == PMIC_IS_PM660)
97 slave_id = 0;
98
Parth Dixit7f683712015-12-23 15:59:16 +053099 get_vibration_type(&vib_config);
Matthew Qine8b71a42015-06-26 17:12:32 +0800100 /* Configure the ACTUATOR TYPE register as ERM*/
Umang Agrawal6df58d72019-05-22 12:06:07 +0530101 pmic_spmi_reg_mask_write(QPNP_HAP_ACT_TYPE_REG(slave_id),
Wufeng Jiang1ce072f2015-08-06 19:07:09 +0800102 QPNP_HAP_ACT_TYPE_MASK,
Parth Dixit7f683712015-12-23 15:59:16 +0530103 VIB_ERM_TYPE == vib_config.vib_type ? QPNP_HAP_ERM
Wufeng Jiang1ce072f2015-08-06 19:07:09 +0800104 : QPNP_HAP_LRA);
Matthew Qine8b71a42015-06-26 17:12:32 +0800105
106 /* Disable auto resonance for ERM */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530107 pmic_spmi_reg_mask_write(QPNP_HAP_LRA_AUTO_RES_REG(slave_id),
Wufeng Jiang1ce072f2015-08-06 19:07:09 +0800108 QPNP_HAP_LRA_AUTO_MASK,
109 QPNP_HAP_LRA_AUTO_DISABLE);
Matthew Qine8b71a42015-06-26 17:12:32 +0800110
111 /* Configure the PLAY MODE register as direct*/
Umang Agrawal6df58d72019-05-22 12:06:07 +0530112 pmic_spmi_reg_mask_write(QPNP_HAP_PLAY_MODE_REG(slave_id),
Wufeng Jiang1ce072f2015-08-06 19:07:09 +0800113 QPNP_HAP_PLAY_MODE_MASK,
114 QPNP_HAP_DIRECT);
Matthew Qine8b71a42015-06-26 17:12:32 +0800115
116 /* Configure the VMAX register */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530117 pmic_spmi_reg_mask_write(QPNP_HAP_VMAX_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800118 QPNP_HAP_VMAX_MASK, QPNP_HAP_VMAX);
119
120 /* Sets current limit to 800mA*/
Umang Agrawal6df58d72019-05-22 12:06:07 +0530121 pmic_spmi_reg_mask_write(QPNP_HAP_ILIM_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800122 QPNP_HAP_ILIM_MASK, QPNP_HAP_ILIM);
123
124 /* Configure the short circuit debounce register as DEB_8CLK*/
Umang Agrawal6df58d72019-05-22 12:06:07 +0530125 pmic_spmi_reg_mask_write(QPNP_HAP_SC_DEB_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800126 QPNP_HAP_SC_DEB_MASK, QPNP_HAP_SC_DEB_8CLK);
127
128 /* Configure the INTERNAL_PWM register as 505KHZ and 13PF*/
Umang Agrawal6df58d72019-05-22 12:06:07 +0530129 pmic_spmi_reg_mask_write(QPNP_HAP_INT_PWM_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800130 QPNP_HAP_INT_PWM_MASK, QPNP_HAP_INT_PWM_505KHZ);
Umang Agrawal6df58d72019-05-22 12:06:07 +0530131 pmic_spmi_reg_mask_write(QPNP_HAP_PWM_CAP_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800132 QPNP_HAP_PWM_CAP_MASK, QPNP_HAP_PWM_CAP_13PF);
133
134 /* Configure the WAVE SHAPE register as SQUARE*/
Umang Agrawal6df58d72019-05-22 12:06:07 +0530135 pmic_spmi_reg_mask_write(QPNP_HAP_WAV_SHAPE_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800136 QPNP_HAP_WAV_SHAPE_MASK, QPNP_HAP_WAV_SHAPE_SQUARE);
137
138 /* Configure RATE_CFG1 and RATE_CFG2 registers for haptic rate. */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530139 pmic_spmi_reg_mask_write(QPNP_HAP_RATE_CFG1_REG(slave_id),
Parth Dixit7f683712015-12-23 15:59:16 +0530140 QPNP_HAP_RATE_CFG1_MASK, vib_config.hap_rate_cfg1);
Umang Agrawal6df58d72019-05-22 12:06:07 +0530141 pmic_spmi_reg_mask_write(QPNP_HAP_RATE_CFG2_REG(slave_id),
Parth Dixit7f683712015-12-23 15:59:16 +0530142 QPNP_HAP_RATE_CFG2_MASK, vib_config.hap_rate_cfg2);
Matthew Qine8b71a42015-06-26 17:12:32 +0800143
144 /* Configure BRAKE register, PATTERN1 & PATTERN2 as VMAX. */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530145 pmic_spmi_reg_mask_write(QPNP_HAP_EN_CTL2_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800146 QPNP_HAP_EN_BRAKE_EN_MASK, QPNP_HAP_EN_BRAKING_EN);
Umang Agrawal6df58d72019-05-22 12:06:07 +0530147 pmic_spmi_reg_mask_write(QPNP_HAP_BRAKE_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800148 QPNP_HAP_BRAKE_VMAX_MASK, QPNP_HAP_BRAKE_VMAX);
149
150 /* Enable control register */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530151 pmic_spmi_reg_mask_write(QPNP_HAP_EN_CTL_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800152 QPNP_HAP_PLAY_MASK, QPNP_HAP_PLAY_EN);
153
154 /* Enable play register */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530155 pmic_spmi_reg_mask_write(QPNP_HAP_PLAY_REG(slave_id), QPNP_HAP_MASK, QPNP_HAP_EN);
Matthew Qine8b71a42015-06-26 17:12:32 +0800156}
157
158/* Turn off vibrator */
Umang Agrawalc1fc0772017-12-19 12:06:49 +0530159void pm_haptic_vib_turn_off(void)
Matthew Qine8b71a42015-06-26 17:12:32 +0800160{
Umang Agrawal6df58d72019-05-22 12:06:07 +0530161 uint32_t pmic = target_get_pmic();
162 uint32_t slave_id = 1;
163
164 if(!target_is_pmi_enabled() && (pmic != PMIC_IS_PM660))
Parth Dixit550ddf32016-11-28 17:00:29 +0530165 return;
166
Umang Agrawal6df58d72019-05-22 12:06:07 +0530167 if (pmic == PMIC_IS_PM660)
168 slave_id = 0;
169
Matthew Qine8b71a42015-06-26 17:12:32 +0800170 /* Disable control register */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530171 pmic_spmi_reg_mask_write(QPNP_HAP_EN_CTL_REG(slave_id),
Matthew Qine8b71a42015-06-26 17:12:32 +0800172 QPNP_HAP_PLAY_MASK, QPNP_HAP_PLAY_DIS);
173
174 /* Disable play register */
Umang Agrawal6df58d72019-05-22 12:06:07 +0530175 pmic_spmi_reg_mask_write(QPNP_HAP_PLAY_REG(slave_id), QPNP_HAP_MASK, QPNP_HAP_DIS);
Matthew Qine8b71a42015-06-26 17:12:32 +0800176}