misc: isa1200: Add regulator support
Signed-off-by: Mohan Pallaka <mpallaka@codeaurora.org>
diff --git a/drivers/misc/isa1200.c b/drivers/misc/isa1200.c
index bb3f9a8..a58c7d6 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, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, 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
@@ -19,6 +19,7 @@
#include <linux/pwm.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
#include <linux/i2c/isa1200.h>
#include "../staging/android/timed_output.h"
@@ -42,6 +43,8 @@
spinlock_t lock;
unsigned int enable;
unsigned int period_ns;
+ bool is_len_gpio_valid;
+ struct regulator **regs;
};
static int isa1200_read_reg(struct i2c_client *client, int reg)
@@ -168,8 +171,14 @@
int value, temp, rc;
gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_len_gpio, 0);
+
udelay(250);
+
gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 1);
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_len_gpio, 1);
value = (haptic->pdata->smart_en << 3) |
(haptic->pdata->is_erm << 5) |
@@ -218,6 +227,99 @@
return rc;
}
+static int isa1200_reg_power(struct isa1200_chip *haptic, bool on)
+{
+ const struct isa1200_regulator *reg_info =
+ haptic->pdata->regulator_info;
+ u8 i, num_reg = haptic->pdata->num_regulators;
+ int rc;
+
+ for (i = 0; i < num_reg; i++) {
+ rc = regulator_set_optimum_mode(haptic->regs[i],
+ on ? reg_info[i].load_uA : 0);
+ if (rc < 0) {
+ pr_err("%s: regulator_set_optimum_mode failed(%d)\n",
+ __func__, rc);
+ goto regs_fail;
+ }
+
+ rc = on ? regulator_enable(haptic->regs[i]) :
+ regulator_disable(haptic->regs[i]);
+ if (rc < 0) {
+ pr_err("%s: regulator %sable fail %d\n", __func__,
+ on ? "en" : "dis", rc);
+ regulator_set_optimum_mode(haptic->regs[i],
+ !on ? reg_info[i].load_uA : 0);
+ goto regs_fail;
+ }
+ }
+
+ return 0;
+
+regs_fail:
+ while (i--) {
+ regulator_set_optimum_mode(haptic->regs[i],
+ !on ? reg_info[i].load_uA : 0);
+ !on ? regulator_enable(haptic->regs[i]) :
+ regulator_disable(haptic->regs[i]);
+ }
+ return rc;
+}
+
+static int isa1200_reg_setup(struct isa1200_chip *haptic, bool on)
+{
+ const struct isa1200_regulator *reg_info =
+ haptic->pdata->regulator_info;
+ u8 i, num_reg = haptic->pdata->num_regulators;
+ int rc = 0;
+
+ /* put regulators */
+ if (on == false) {
+ i = num_reg;
+ goto put_regs;
+ }
+
+ haptic->regs = kzalloc(num_reg * sizeof(struct regulator *),
+ GFP_KERNEL);
+ if (!haptic->regs) {
+ pr_err("unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < num_reg; i++) {
+ haptic->regs[i] = regulator_get(&haptic->client->dev,
+ reg_info[i].name);
+ if (IS_ERR(haptic->regs[i])) {
+ rc = PTR_ERR(haptic->regs[i]);
+ pr_err("%s:regulator get failed(%d)\n", __func__, rc);
+ goto put_regs;
+ }
+
+ if (regulator_count_voltages(haptic->regs[i]) > 0) {
+ rc = regulator_set_voltage(haptic->regs[i],
+ reg_info[i].min_uV, reg_info[i].max_uV);
+ if (rc) {
+ pr_err("%s: regulator_set_voltage failed(%d)\n",
+ __func__, rc);
+ regulator_put(haptic->regs[i]);
+ goto put_regs;
+ }
+ }
+ }
+
+ return rc;
+
+put_regs:
+ while (i--) {
+ if (regulator_count_voltages(haptic->regs[i]) > 0)
+ regulator_set_voltage(haptic->regs[i], 0,
+ reg_info[i].max_uV);
+ regulator_put(haptic->regs[i]);
+ }
+ kfree(haptic->regs);
+ return rc;
+}
+
static int __devinit isa1200_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -255,6 +357,22 @@
haptic->enable = 0;
haptic->pdata = pdata;
+ if (pdata->regulator_info) {
+ ret = isa1200_reg_setup(haptic, true);
+ if (ret) {
+ dev_err(&client->dev, "%s: regulator setup failed\n",
+ __func__);
+ goto reg_setup_fail;
+ }
+
+ ret = isa1200_reg_power(haptic, true);
+ if (ret) {
+ dev_err(&client->dev, "%s: regulator power failed\n",
+ __func__);
+ goto reg_pwr_fail;
+ }
+ }
+
if (pdata->power_on) {
ret = pdata->power_on(1);
if (ret) {
@@ -282,22 +400,39 @@
ret = gpio_is_valid(pdata->hap_en_gpio);
if (ret) {
- ret = gpio_request(pdata->hap_en_gpio, "haptic_gpio");
+ ret = gpio_request(pdata->hap_en_gpio, "haptic_en_gpio");
if (ret) {
dev_err(&client->dev, "%s: gpio %d request failed\n",
__func__, pdata->hap_en_gpio);
- goto gpio_fail;
+ goto hen_gpio_fail;
}
} else {
dev_err(&client->dev, "%s: Invalid gpio %d\n", __func__,
pdata->hap_en_gpio);
- goto gpio_fail;
+ goto hen_gpio_fail;
+ }
+
+ haptic->is_len_gpio_valid = true;
+ ret = gpio_is_valid(haptic->pdata->hap_len_gpio);
+ if (ret) {
+ ret = gpio_request(pdata->hap_len_gpio,
+ "haptic_ldo_gpio");
+ if (ret) {
+ dev_err(&client->dev,
+ "%s: gpio %d request failed\n",
+ __func__, pdata->hap_len_gpio);
+ goto len_gpio_fail;
+ }
+ } else {
+ dev_err(&client->dev, "%s: gpio is not used/Invalid %d\n",
+ __func__, pdata->hap_len_gpio);
+ haptic->is_len_gpio_valid = false;
}
ret = isa1200_setup(client);
if (ret) {
dev_err(&client->dev, "%s: setup fail %d\n", __func__, ret);
- goto gpio_fail;
+ goto setup_fail;
}
if (haptic->pdata->mode_ctrl == PWM_INPUT_MODE) {
@@ -316,12 +451,23 @@
reset_hctrl0:
i2c_smbus_write_byte_data(client, ISA1200_HCTRL0,
ISA1200_HCTRL0_RESET);
-gpio_fail:
+setup_fail:
+ if (haptic->is_len_gpio_valid == true)
+ gpio_free(pdata->hap_len_gpio);
+len_gpio_fail:
+ gpio_free(pdata->hap_en_gpio);
+hen_gpio_fail:
timed_output_dev_unregister(&haptic->dev);
timed_reg_fail:
if (pdata->power_on)
pdata->power_on(0);
pwr_up_fail:
+ if (pdata->regulator_info)
+ isa1200_reg_power(haptic, false);
+reg_pwr_fail:
+ if (pdata->regulator_info)
+ isa1200_reg_setup(haptic, false);
+reg_setup_fail:
kfree(haptic);
mem_alloc_fail:
if (pdata->dev_setup)
@@ -343,7 +489,10 @@
pwm_free(haptic->pwm);
timed_output_dev_unregister(&haptic->dev);
+
gpio_free(haptic->pdata->hap_en_gpio);
+ if (haptic->is_len_gpio_valid == true)
+ gpio_free(haptic->pdata->hap_len_gpio);
/* reset hardware registers */
i2c_smbus_write_byte_data(client, ISA1200_HCTRL0,
@@ -351,13 +500,19 @@
i2c_smbus_write_byte_data(client, ISA1200_HCTRL1,
ISA1200_HCTRL1_RESET);
- if (haptic->pdata->dev_setup)
- haptic->pdata->dev_setup(false);
/* power-off the chip */
+ if (haptic->pdata->regulator_info) {
+ isa1200_reg_power(haptic, false);
+ isa1200_reg_setup(haptic, false);
+ }
+
if (haptic->pdata->power_on)
haptic->pdata->power_on(0);
+ if (haptic->pdata->dev_setup)
+ haptic->pdata->dev_setup(false);
+
kfree(haptic);
return 0;
}
@@ -373,6 +528,13 @@
/* turn-off current vibration */
isa1200_vib_set(haptic, 0);
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_len_gpio, 0);
+
+ if (haptic->pdata->regulator_info)
+ isa1200_reg_power(haptic, false);
+
if (haptic->pdata->power_on) {
ret = haptic->pdata->power_on(0);
if (ret) {
@@ -389,6 +551,9 @@
struct isa1200_chip *haptic = i2c_get_clientdata(client);
int ret;
+ if (haptic->pdata->regulator_info)
+ isa1200_reg_power(haptic, true);
+
if (haptic->pdata->power_on) {
ret = haptic->pdata->power_on(1);
if (ret) {