misc: isa1200: Add support for clock enable
ISA1200 uses clock to generate pwm for vibration. Add
a callback api to control the clock.
CRs-fixed: 357656
Change-Id: Iac1d0cdb3ac950b7bbc2afbe3a92b0e0292e3811
Signed-off-by: Mohan Pallaka <mpallaka@codeaurora.org>
diff --git a/drivers/misc/isa1200.c b/drivers/misc/isa1200.c
index 31c79a0..555dfdd 100644
--- a/drivers/misc/isa1200.c
+++ b/drivers/misc/isa1200.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2009 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -32,6 +32,7 @@
#define ISA1200_HCTRL5_VIB_STRT 0xD5
#define ISA1200_HCTRL5_VIB_STOP 0x6B
+#define ISA1200_POWER_DOWN_MASK 0x7F
struct isa1200_chip {
struct i2c_client *client;
@@ -45,6 +46,8 @@
unsigned int period_ns;
bool is_len_gpio_valid;
struct regulator **regs;
+ bool clk_on;
+ u8 hctrl0_val;
};
static int isa1200_read_reg(struct i2c_client *client, int reg)
@@ -74,32 +77,111 @@
int rc = 0;
if (enable) {
+ /* if hen and len are seperate then enable hen
+ * otherwise set normal mode bit */
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 1);
+ else {
+ rc = isa1200_write_reg(haptic->client, ISA1200_HCTRL0,
+ haptic->hctrl0_val | ~ISA1200_POWER_DOWN_MASK);
+ if (rc < 0) {
+ pr_err("%s: i2c write failure\n", __func__);
+ return;
+ }
+ }
+
if (haptic->pdata->mode_ctrl == PWM_INPUT_MODE) {
int period_us = haptic->period_ns / 1000;
+
rc = pwm_config(haptic->pwm,
(period_us * haptic->pdata->duty) / 100,
period_us);
- if (rc < 0)
+ if (rc < 0) {
pr_err("%s: pwm_config fail\n", __func__);
+ goto chip_dwn;
+ }
+
rc = pwm_enable(haptic->pwm);
- if (rc < 0)
+ if (rc < 0) {
pr_err("%s: pwm_enable fail\n", __func__);
+ goto chip_dwn;
+ }
} else if (haptic->pdata->mode_ctrl == PWM_GEN_MODE) {
+ /* vote for clock */
+ if (haptic->pdata->clk_enable && !haptic->clk_on) {
+ rc = haptic->pdata->clk_enable(true);
+ if (rc < 0) {
+ pr_err("%s: clk enable failed\n",
+ __func__);
+ goto chip_dwn;
+ }
+ haptic->clk_on = true;
+ }
+
rc = isa1200_write_reg(haptic->client,
ISA1200_HCTRL5,
ISA1200_HCTRL5_VIB_STRT);
- if (rc < 0)
+ if (rc < 0) {
pr_err("%s: start vibartion fail\n", __func__);
+ goto dis_clk;
+ }
}
} else {
- if (haptic->pdata->mode_ctrl == PWM_INPUT_MODE)
+ /* if hen and len are seperate then pull down hen
+ * otherwise set power down bit */
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ else {
+ rc = isa1200_write_reg(haptic->client, ISA1200_HCTRL0,
+ haptic->hctrl0_val & ISA1200_POWER_DOWN_MASK);
+ if (rc < 0) {
+ pr_err("%s: i2c write failure\n", __func__);
+ return;
+ }
+ }
+
+ if (haptic->pdata->mode_ctrl == PWM_INPUT_MODE) {
pwm_disable(haptic->pwm);
- else if (haptic->pdata->mode_ctrl == PWM_GEN_MODE) {
+ } else if (haptic->pdata->mode_ctrl == PWM_GEN_MODE) {
rc = isa1200_write_reg(haptic->client,
ISA1200_HCTRL5,
ISA1200_HCTRL5_VIB_STOP);
if (rc < 0)
pr_err("%s: stop vibartion fail\n", __func__);
+
+ /* de-vote clock */
+ if (haptic->pdata->clk_enable && haptic->clk_on) {
+ rc = haptic->pdata->clk_enable(false);
+ if (rc < 0) {
+ pr_err("%s: clk disable failed\n",
+ __func__);
+ return;
+ }
+ haptic->clk_on = false;
+ }
+ }
+ }
+
+ return;
+
+dis_clk:
+ if (haptic->pdata->clk_enable && haptic->clk_on) {
+ rc = haptic->pdata->clk_enable(false);
+ if (rc < 0) {
+ pr_err("%s: clk disable failed\n", __func__);
+ return;
+ }
+ haptic->clk_on = false;
+ }
+chip_dwn:
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ else {
+ rc = isa1200_write_reg(haptic->client, ISA1200_HCTRL0,
+ haptic->hctrl0_val & ISA1200_POWER_DOWN_MASK);
+ if (rc < 0) {
+ pr_err("%s: i2c write failure\n", __func__);
+ return;
}
}
}
@@ -168,7 +250,8 @@
static int isa1200_setup(struct i2c_client *client)
{
struct isa1200_chip *haptic = i2c_get_clientdata(client);
- int value, temp, rc;
+ int temp, rc;
+ u8 value;
gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
if (haptic->is_len_gpio_valid == true)
@@ -218,6 +301,20 @@
goto reset_hctrl1;
}
+ /* if hen and len are seperate then pull down hen
+ * otherwise set power down bit */
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ else {
+ rc = isa1200_write_reg(client, ISA1200_HCTRL0,
+ value & ISA1200_POWER_DOWN_MASK);
+ if (rc < 0) {
+ pr_err("%s: i2c write failure\n", __func__);
+ goto reset_hctrl1;
+ }
+ }
+
+ haptic->hctrl0_val = value;
dump_isa1200_reg("new:", client);
return 0;
@@ -388,6 +485,7 @@
spin_lock_init(&haptic->lock);
INIT_WORK(&haptic->work, isa1200_chip_work);
+ haptic->clk_on = false;
hrtimer_init(&haptic->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
haptic->timer.function = isa1200_vib_timer_func;