mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 12:52:29 -04:00
Input: cap11xx - refactor code for better CAP1114 support.
Extend cap11xx_hw_model structure to support CAP1114 with different register offsets and hardware characteristics: - led_output_control_reg_base: different address on CAP1114 - sensor_input_reg_base: different address on CAP1114 - num_sensor_thresholds: separate value from num_channels for CAP1114 - has_repeat_en: repeat enable support, disabled by default on CAP1114 Include linux/bits.h, update the register operations related to LEDs. Signed-off-by: Jun Yan <jerrysteve1101@gmail.com> Link: https://patch.msgid.link/20260617150318.753148-8-jerrysteve1101@gmail.com Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
* (c) 2014 Daniel Mack <linux@zonque.org>
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@@ -22,6 +23,7 @@
|
||||
#define CAP11XX_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
|
||||
#define CAP11XX_REG_MAIN_CONTROL_DLSEEP BIT(4)
|
||||
#define CAP11XX_REG_SENSOR_INPUT 0x03
|
||||
#define CAP1114_REG_BUTTON_STATUS2 0x04
|
||||
#define CAP11XX_REG_SENOR_DELTA(X) (0x10 + (X))
|
||||
#define CAP11XX_REG_SENSITIVITY_CONTROL 0x1f
|
||||
#define CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MASK 0x70
|
||||
@@ -36,7 +38,6 @@
|
||||
#define CAP11XX_REG_LED_DUTY_CYCLE_4 0x93
|
||||
|
||||
#define CAP11XX_REG_LED_DUTY_MAX_MASK (0xf0)
|
||||
#define CAP11XX_REG_LED_DUTY_MAX_MASK_SHIFT (4)
|
||||
#define CAP11XX_REG_LED_DUTY_MAX_VALUE (15)
|
||||
|
||||
#define CAP11XX_REG_PRODUCT_ID 0xfd
|
||||
@@ -77,10 +78,14 @@ struct cap11xx_priv {
|
||||
|
||||
struct cap11xx_hw_model {
|
||||
u8 product_id;
|
||||
u8 led_output_control_reg_base;
|
||||
u8 sensor_input_reg_base;
|
||||
unsigned int num_channels;
|
||||
unsigned int num_leds;
|
||||
unsigned int num_sensor_thresholds;
|
||||
bool has_gain;
|
||||
bool has_irq_config;
|
||||
bool has_repeat_en;
|
||||
bool has_sensitivity_control;
|
||||
bool has_signal_guard;
|
||||
};
|
||||
@@ -103,6 +108,7 @@ static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
|
||||
switch (reg) {
|
||||
case CAP11XX_REG_MAIN_CONTROL:
|
||||
case CAP11XX_REG_SENSOR_INPUT:
|
||||
case CAP1114_REG_BUTTON_STATUS2:
|
||||
case CAP11XX_REG_SENOR_DELTA(0):
|
||||
case CAP11XX_REG_SENOR_DELTA(1):
|
||||
case CAP11XX_REG_SENOR_DELTA(2):
|
||||
@@ -211,8 +217,8 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv)
|
||||
}
|
||||
|
||||
if (!of_property_read_u32_array(node, "microchip,input-threshold",
|
||||
priv->thresholds, priv->model->num_channels)) {
|
||||
for (i = 0; i < priv->model->num_channels; i++) {
|
||||
priv->thresholds, priv->model->num_sensor_thresholds)) {
|
||||
for (i = 0; i < priv->model->num_sensor_thresholds; i++) {
|
||||
if (priv->thresholds[i] > 127) {
|
||||
dev_err(dev, "Invalid input-threshold value %u\n",
|
||||
priv->thresholds[i]);
|
||||
@@ -286,10 +292,12 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv)
|
||||
of_property_read_u32_array(node, "linux,keycodes",
|
||||
priv->keycodes, priv->model->num_channels);
|
||||
|
||||
/* Disable autorepeat. The Linux input system has its own handling. */
|
||||
error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
|
||||
if (error)
|
||||
return error;
|
||||
if (priv->model->has_repeat_en) {
|
||||
/* Disable autorepeat. The Linux input system has its own handling. */
|
||||
error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -308,7 +316,7 @@ static irqreturn_t cap11xx_thread_func(int irq_num, void *data)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = regmap_read(priv->regmap, CAP11XX_REG_SENSOR_INPUT, &status);
|
||||
ret = regmap_read(priv->regmap, priv->model->sensor_input_reg_base, &status);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@@ -361,10 +369,16 @@ static int cap11xx_led_set(struct led_classdev *cdev,
|
||||
* limitation. Brightness levels per LED are either
|
||||
* 0 (OFF) and 1 (ON).
|
||||
*/
|
||||
return regmap_update_bits(priv->regmap,
|
||||
CAP11XX_REG_LED_OUTPUT_CONTROL,
|
||||
BIT(led->reg),
|
||||
value ? BIT(led->reg) : 0);
|
||||
if (led->reg >= 8)
|
||||
return regmap_update_bits(priv->regmap,
|
||||
priv->model->led_output_control_reg_base + 1,
|
||||
BIT(led->reg - 8),
|
||||
value ? BIT(led->reg - 8) : 0);
|
||||
else
|
||||
return regmap_update_bits(priv->regmap,
|
||||
priv->model->led_output_control_reg_base,
|
||||
BIT(led->reg),
|
||||
value ? BIT(led->reg) : 0);
|
||||
}
|
||||
|
||||
static int cap11xx_init_leds(struct device *dev,
|
||||
@@ -374,6 +388,7 @@ static int cap11xx_init_leds(struct device *dev,
|
||||
struct cap11xx_led *led;
|
||||
int cnt = of_get_child_count(node);
|
||||
int error;
|
||||
u32 duty_val;
|
||||
|
||||
if (!num_leds || !cnt)
|
||||
return 0;
|
||||
@@ -387,15 +402,26 @@ static int cap11xx_init_leds(struct device *dev,
|
||||
|
||||
priv->leds = led;
|
||||
|
||||
/* Set all LEDs to off */
|
||||
error = regmap_update_bits(priv->regmap,
|
||||
CAP11XX_REG_LED_OUTPUT_CONTROL, 0xff, 0);
|
||||
priv->model->led_output_control_reg_base,
|
||||
GENMASK(min(num_leds, 8) - 1, 0), 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (num_leds > 8) {
|
||||
error = regmap_update_bits(priv->regmap,
|
||||
priv->model->led_output_control_reg_base + 1,
|
||||
GENMASK(num_leds - 8 - 1, 0), 0);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
duty_val = FIELD_PREP(CAP11XX_REG_LED_DUTY_MAX_MASK,
|
||||
CAP11XX_REG_LED_DUTY_MAX_VALUE);
|
||||
|
||||
error = regmap_update_bits(priv->regmap, CAP11XX_REG_LED_DUTY_CYCLE_4,
|
||||
CAP11XX_REG_LED_DUTY_MAX_MASK,
|
||||
CAP11XX_REG_LED_DUTY_MAX_VALUE <<
|
||||
CAP11XX_REG_LED_DUTY_MAX_MASK_SHIFT);
|
||||
CAP11XX_REG_LED_DUTY_MAX_MASK, duty_val);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -561,41 +587,64 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
|
||||
}
|
||||
|
||||
static const struct cap11xx_hw_model cap1106_model = {
|
||||
.product_id = 0x55, .num_channels = 6, .num_leds = 0,
|
||||
.product_id = 0x55,
|
||||
.num_channels = 6, .num_leds = 0, .num_sensor_thresholds = 6,
|
||||
.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
|
||||
.has_gain = true,
|
||||
.has_irq_config = true,
|
||||
.has_repeat_en = true,
|
||||
};
|
||||
|
||||
static const struct cap11xx_hw_model cap1126_model = {
|
||||
.product_id = 0x53, .num_channels = 6, .num_leds = 2,
|
||||
.product_id = 0x53,
|
||||
.num_channels = 6, .num_leds = 2, .num_sensor_thresholds = 6,
|
||||
.led_output_control_reg_base = CAP11XX_REG_LED_OUTPUT_CONTROL,
|
||||
.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
|
||||
.has_gain = true,
|
||||
.has_irq_config = true,
|
||||
.has_repeat_en = true,
|
||||
};
|
||||
|
||||
static const struct cap11xx_hw_model cap1188_model = {
|
||||
.product_id = 0x50, .num_channels = 8, .num_leds = 8,
|
||||
.product_id = 0x50,
|
||||
.num_channels = 8, .num_leds = 8, .num_sensor_thresholds = 8,
|
||||
.led_output_control_reg_base = CAP11XX_REG_LED_OUTPUT_CONTROL,
|
||||
.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
|
||||
.has_gain = true,
|
||||
.has_irq_config = true,
|
||||
.has_repeat_en = true,
|
||||
};
|
||||
|
||||
static const struct cap11xx_hw_model cap1203_model = {
|
||||
.product_id = 0x6d, .num_channels = 3, .num_leds = 0,
|
||||
.product_id = 0x6d,
|
||||
.num_channels = 3, .num_leds = 0, .num_sensor_thresholds = 3,
|
||||
.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
|
||||
.has_repeat_en = true,
|
||||
};
|
||||
|
||||
static const struct cap11xx_hw_model cap1206_model = {
|
||||
.product_id = 0x67, .num_channels = 6, .num_leds = 0,
|
||||
.product_id = 0x67,
|
||||
.num_channels = 6, .num_leds = 0, .num_sensor_thresholds = 6,
|
||||
.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
|
||||
.has_repeat_en = true,
|
||||
};
|
||||
|
||||
static const struct cap11xx_hw_model cap1293_model = {
|
||||
.product_id = 0x6f, .num_channels = 3, .num_leds = 0,
|
||||
.product_id = 0x6f,
|
||||
.num_channels = 3, .num_leds = 0, .num_sensor_thresholds = 3,
|
||||
.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
|
||||
.has_gain = true,
|
||||
.has_repeat_en = true,
|
||||
.has_sensitivity_control = true,
|
||||
.has_signal_guard = true,
|
||||
};
|
||||
|
||||
static const struct cap11xx_hw_model cap1298_model = {
|
||||
.product_id = 0x71, .num_channels = 8, .num_leds = 0,
|
||||
.product_id = 0x71,
|
||||
.num_channels = 8, .num_leds = 0, .num_sensor_thresholds = 8,
|
||||
.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
|
||||
.has_gain = true,
|
||||
.has_repeat_en = true,
|
||||
.has_sensitivity_control = true,
|
||||
.has_signal_guard = true,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user