Merge "input: misc: pat9125: add regulator framework support"
This commit is contained in:
commit
ab814b99a0
4 changed files with 154 additions and 9 deletions
|
@ -10,6 +10,8 @@ Required properties:
|
||||||
- reg : i2c slave address of the device.
|
- reg : i2c slave address of the device.
|
||||||
- interrupt-parent : parent of interrupt.
|
- interrupt-parent : parent of interrupt.
|
||||||
- interrupts : interrupt to indicate motion of the rotating switch.
|
- interrupts : interrupt to indicate motion of the rotating switch.
|
||||||
|
- vdd-supply : Power supply needed to power up the device.
|
||||||
|
- vld-supply : Power source required to power up I2C bus.
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- pixart,inverse-x : boolean, use this to invert the x data before sending it to input framework
|
- pixart,inverse-x : boolean, use this to invert the x data before sending it to input framework
|
||||||
|
@ -44,6 +46,8 @@ Example:
|
||||||
reg = <0x75>;
|
reg = <0x75>;
|
||||||
interrupt-parent = <&msm_gpio>;
|
interrupt-parent = <&msm_gpio>;
|
||||||
interrupts = <98 0x2008>;
|
interrupts = <98 0x2008>;
|
||||||
|
vdd-supply = <&pm8110_l5>;
|
||||||
|
vld-supply = <&pm8110_l17>;
|
||||||
pixart,irq-gpio = <&msm_gpio 98 0x2008>;
|
pixart,irq-gpio = <&msm_gpio 98 0x2008>;
|
||||||
pinctrl-names = "pmx_rot_switch_active",
|
pinctrl-names = "pmx_rot_switch_active",
|
||||||
"pmx_rot_switch_suspend",
|
"pmx_rot_switch_suspend",
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
#include "pixart_ots.h"
|
#include "pixart_ots.h"
|
||||||
|
|
||||||
struct pixart_pat9125_data {
|
struct pixart_pat9125_data {
|
||||||
|
@ -22,6 +23,8 @@ struct pixart_pat9125_data {
|
||||||
bool press_en;
|
bool press_en;
|
||||||
bool inverse_x;
|
bool inverse_x;
|
||||||
bool inverse_y;
|
bool inverse_y;
|
||||||
|
struct regulator *vdd;
|
||||||
|
struct regulator *vld;
|
||||||
struct pinctrl *pinctrl;
|
struct pinctrl *pinctrl;
|
||||||
struct pinctrl_state *pinctrl_state_active;
|
struct pinctrl_state *pinctrl_state_active;
|
||||||
struct pinctrl_state *pinctrl_state_suspend;
|
struct pinctrl_state *pinctrl_state_suspend;
|
||||||
|
@ -150,7 +153,7 @@ static ssize_t pat9125_test_store(struct device *dev,
|
||||||
int reg_data = 0, i;
|
int reg_data = 0, i;
|
||||||
long rd_addr, wr_addr, wr_data;
|
long rd_addr, wr_addr, wr_data;
|
||||||
struct pixart_pat9125_data *data =
|
struct pixart_pat9125_data *data =
|
||||||
(struct pixart_pat9125_data *)dev->driver_data;
|
(struct pixart_pat9125_data *) dev_get_drvdata(dev);
|
||||||
struct i2c_client *client = data->client;
|
struct i2c_client *client = data->client;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(s); i++)
|
for (i = 0; i < sizeof(s); i++)
|
||||||
|
@ -238,6 +241,98 @@ static int pixart_pinctrl_init(struct pixart_pat9125_data *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pat9125_regulator_init(struct pixart_pat9125_data *data)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
struct device *dev = &data->client->dev;
|
||||||
|
|
||||||
|
data->vdd = devm_regulator_get(dev, "vdd");
|
||||||
|
if (IS_ERR(data->vdd)) {
|
||||||
|
dev_err(dev, "Failed to get regulator vdd %ld\n",
|
||||||
|
PTR_ERR(data->vdd));
|
||||||
|
return PTR_ERR(data->vdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->vld = devm_regulator_get(dev, "vld");
|
||||||
|
if (IS_ERR(data->vld)) {
|
||||||
|
dev_err(dev, "Failed to get regulator vld %ld\n",
|
||||||
|
PTR_ERR(data->vld));
|
||||||
|
return PTR_ERR(data->vld);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regulator_set_voltage(data->vdd, VDD_VTG_MIN_UV, VDD_VTG_MAX_UV);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to set voltage for vdd reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regulator_set_load(data->vdd, VDD_ACTIVE_LOAD_UA);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "Failed to set opt mode for vdd reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regulator_set_voltage(data->vld, VLD_VTG_MIN_UV, VLD_VTG_MAX_UV);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to set voltage for vld reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regulator_set_load(data->vld, VLD_ACTIVE_LOAD_UA);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "Failed to set opt mode for vld reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pat9125_power_on(struct pixart_pat9125_data *data, bool on)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
struct device *dev = &data->client->dev;
|
||||||
|
|
||||||
|
if (on) {
|
||||||
|
err = regulator_enable(data->vdd);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to enable vdd reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep_range(DELAY_BETWEEN_REG_US, DELAY_BETWEEN_REG_US + 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize pixart sensor after some delay, when vdd
|
||||||
|
* regulator is enabled
|
||||||
|
*/
|
||||||
|
if (!ots_sensor_init(data->client)) {
|
||||||
|
err = -ENODEV;
|
||||||
|
dev_err(dev, "Failed to initialize sensor %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regulator_enable(data->vld);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to enable vld reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = regulator_disable(data->vld);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to disable vld reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = regulator_disable(data->vdd);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to disable vdd reg %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int pat9125_parse_dt(struct device *dev,
|
static int pat9125_parse_dt(struct device *dev,
|
||||||
struct pixart_pat9125_data *data)
|
struct pixart_pat9125_data *data)
|
||||||
{
|
{
|
||||||
|
@ -351,9 +446,16 @@ static int pat9125_i2c_probe(struct i2c_client *client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ots_sensor_init(client)) {
|
err = pat9125_regulator_init(data);
|
||||||
err = -ENODEV;
|
if (err) {
|
||||||
goto err_sensor_init;
|
dev_err(dev, "Failed to init regulator, %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pat9125_power_on(data, true);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to power-on the sensor %d\n", err);
|
||||||
|
goto err_power_on;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devm_request_threaded_irq(dev, client->irq, NULL, pat9125_irq,
|
err = devm_request_threaded_irq(dev, client->irq, NULL, pat9125_irq,
|
||||||
|
@ -374,7 +476,11 @@ static int pat9125_i2c_probe(struct i2c_client *client,
|
||||||
|
|
||||||
err_sysfs_create:
|
err_sysfs_create:
|
||||||
err_request_threaded_irq:
|
err_request_threaded_irq:
|
||||||
err_sensor_init:
|
err_power_on:
|
||||||
|
regulator_set_load(data->vdd, 0);
|
||||||
|
regulator_set_load(data->vld, 0);
|
||||||
|
if (pat9125_power_on(data, false) < 0)
|
||||||
|
dev_err(dev, "Failed to disable regulators\n");
|
||||||
if (data->pinctrl)
|
if (data->pinctrl)
|
||||||
if (pinctrl_select_state(data->pinctrl,
|
if (pinctrl_select_state(data->pinctrl,
|
||||||
data->pinctrl_state_release) < 0)
|
data->pinctrl_state_release) < 0)
|
||||||
|
@ -388,10 +494,14 @@ static int pat9125_i2c_remove(struct i2c_client *client)
|
||||||
struct pixart_pat9125_data *data = i2c_get_clientdata(client);
|
struct pixart_pat9125_data *data = i2c_get_clientdata(client);
|
||||||
struct device *dev = &data->client->dev;
|
struct device *dev = &data->client->dev;
|
||||||
|
|
||||||
|
sysfs_remove_group(&(data->input->dev.kobj), &pat9125_attr_grp);
|
||||||
if (data->pinctrl)
|
if (data->pinctrl)
|
||||||
if (pinctrl_select_state(data->pinctrl,
|
if (pinctrl_select_state(data->pinctrl,
|
||||||
data->pinctrl_state_release) < 0)
|
data->pinctrl_state_release) < 0)
|
||||||
dev_err(dev, "Couldn't set pin to release state\n");
|
dev_err(dev, "Couldn't set pin to release state\n");
|
||||||
|
regulator_set_load(data->vdd, 0);
|
||||||
|
regulator_set_load(data->vld, 0);
|
||||||
|
pat9125_power_on(data, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +509,7 @@ static int pat9125_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct pixart_pat9125_data *data =
|
struct pixart_pat9125_data *data =
|
||||||
(struct pixart_pat9125_data *)dev->driver_data;
|
(struct pixart_pat9125_data *) dev_get_drvdata(dev);
|
||||||
|
|
||||||
disable_irq(data->client->irq);
|
disable_irq(data->client->irq);
|
||||||
if (data->pinctrl) {
|
if (data->pinctrl) {
|
||||||
|
@ -410,6 +520,12 @@ static int pat9125_suspend(struct device *dev)
|
||||||
rc);
|
rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = pat9125_power_on(data, false);
|
||||||
|
if (rc) {
|
||||||
|
dev_err(dev, "Failed to disable regulators %d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +533,7 @@ static int pat9125_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct pixart_pat9125_data *data =
|
struct pixart_pat9125_data *data =
|
||||||
(struct pixart_pat9125_data *)dev->driver_data;
|
(struct pixart_pat9125_data *) dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (data->pinctrl) {
|
if (data->pinctrl) {
|
||||||
rc = pinctrl_select_state(data->pinctrl,
|
rc = pinctrl_select_state(data->pinctrl,
|
||||||
|
@ -426,9 +542,26 @@ static int pat9125_resume(struct device *dev)
|
||||||
dev_err(dev, "Could not set pin to active state %d\n",
|
dev_err(dev, "Could not set pin to active state %d\n",
|
||||||
rc);
|
rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = pat9125_power_on(data, true);
|
||||||
|
if (rc) {
|
||||||
|
dev_err(dev, "Failed to power-on the sensor %d\n", rc);
|
||||||
|
goto err_sensor_init;
|
||||||
|
}
|
||||||
|
|
||||||
enable_irq(data->client->irq);
|
enable_irq(data->client->irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_sensor_init:
|
||||||
|
if (data->pinctrl)
|
||||||
|
if (pinctrl_select_state(data->pinctrl,
|
||||||
|
data->pinctrl_state_suspend) < 0)
|
||||||
|
dev_err(dev, "Couldn't set pin to suspend state\n");
|
||||||
|
if (pat9125_power_on(data, false) < 0)
|
||||||
|
dev_err(dev, "Failed to disable regulators\n");
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id pat9125_device_id[] = {
|
static const struct i2c_device_id pat9125_device_id[] = {
|
||||||
|
|
|
@ -19,7 +19,8 @@ static void ots_write_read(struct i2c_client *client, u8 address, u8 wdata)
|
||||||
|
|
||||||
bool ots_sensor_init(struct i2c_client *client)
|
bool ots_sensor_init(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
unsigned char sensor_pid = 0, read_id_ok = 0;
|
u8 sensor_pid = 0;
|
||||||
|
bool read_id_ok = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read sensor_pid in address 0x00 to check if the
|
* Read sensor_pid in address 0x00 to check if the
|
||||||
|
@ -28,7 +29,7 @@ bool ots_sensor_init(struct i2c_client *client)
|
||||||
sensor_pid = read_data(client, PIXART_PAT9125_PRODUCT_ID1_REG);
|
sensor_pid = read_data(client, PIXART_PAT9125_PRODUCT_ID1_REG);
|
||||||
|
|
||||||
if (sensor_pid == PIXART_PAT9125_SENSOR_ID) {
|
if (sensor_pid == PIXART_PAT9125_SENSOR_ID) {
|
||||||
read_id_ok = 1;
|
read_id_ok = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PAT9125 sensor recommended settings:
|
* PAT9125 sensor recommended settings:
|
||||||
|
|
|
@ -13,6 +13,13 @@
|
||||||
#define PINCTRL_STATE_ACTIVE "pmx_rot_switch_active"
|
#define PINCTRL_STATE_ACTIVE "pmx_rot_switch_active"
|
||||||
#define PINCTRL_STATE_SUSPEND "pmx_rot_switch_suspend"
|
#define PINCTRL_STATE_SUSPEND "pmx_rot_switch_suspend"
|
||||||
#define PINCTRL_STATE_RELEASE "pmx_rot_switch_release"
|
#define PINCTRL_STATE_RELEASE "pmx_rot_switch_release"
|
||||||
|
#define VDD_VTG_MIN_UV 1800000
|
||||||
|
#define VDD_VTG_MAX_UV 1800000
|
||||||
|
#define VDD_ACTIVE_LOAD_UA 10000
|
||||||
|
#define VLD_VTG_MIN_UV 2800000
|
||||||
|
#define VLD_VTG_MAX_UV 3300000
|
||||||
|
#define VLD_ACTIVE_LOAD_UA 10000
|
||||||
|
#define DELAY_BETWEEN_REG_US 20000
|
||||||
|
|
||||||
/* Register addresses */
|
/* Register addresses */
|
||||||
#define PIXART_PAT9125_PRODUCT_ID1_REG 0x00
|
#define PIXART_PAT9125_PRODUCT_ID1_REG 0x00
|
||||||
|
|
Loading…
Add table
Reference in a new issue