mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 11:13:58 +08:00
Merge branch 'next' into for-linus
Prepare second round of input updates for 4.18 merge window.
This commit is contained in:
commit
01f7e67a05
@ -0,0 +1,23 @@
|
||||
Spreadtrum SC27xx PMIC Vibrator
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "sprd,sc2731-vibrator".
|
||||
- reg: address of vibrator control register.
|
||||
|
||||
Example :
|
||||
|
||||
sc2731_pmic: pmic@0 {
|
||||
compatible = "sprd,sc2731";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <26000000>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vibrator@eb4 {
|
||||
compatible = "sprd,sc2731-vibrator";
|
||||
reg = <0xeb4>;
|
||||
};
|
||||
};
|
@ -131,8 +131,10 @@ EXPORT_SYMBOL(input_mt_destroy_slots);
|
||||
* inactive, or if the tool type is changed, a new tracking id is
|
||||
* assigned to the slot. The tool type is only reported if the
|
||||
* corresponding absbit field is set.
|
||||
*
|
||||
* Returns true if contact is active.
|
||||
*/
|
||||
void input_mt_report_slot_state(struct input_dev *dev,
|
||||
bool input_mt_report_slot_state(struct input_dev *dev,
|
||||
unsigned int tool_type, bool active)
|
||||
{
|
||||
struct input_mt *mt = dev->mt;
|
||||
@ -140,22 +142,24 @@ void input_mt_report_slot_state(struct input_dev *dev,
|
||||
int id;
|
||||
|
||||
if (!mt)
|
||||
return;
|
||||
return false;
|
||||
|
||||
slot = &mt->slots[mt->slot];
|
||||
slot->frame = mt->frame;
|
||||
|
||||
if (!active) {
|
||||
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
|
||||
if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type)
|
||||
if (id < 0)
|
||||
id = input_mt_new_trkid(mt);
|
||||
|
||||
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
|
||||
input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_report_slot_state);
|
||||
|
||||
|
@ -45,7 +45,7 @@ struct event_dev {
|
||||
static irqreturn_t events_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct event_dev *edev = dev_id;
|
||||
unsigned type, code, value;
|
||||
unsigned int type, code, value;
|
||||
|
||||
type = __raw_readl(edev->addr + REG_READ);
|
||||
code = __raw_readl(edev->addr + REG_READ);
|
||||
@ -57,7 +57,7 @@ static irqreturn_t events_interrupt(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
static void events_import_bits(struct event_dev *edev,
|
||||
unsigned long bits[], unsigned type, size_t count)
|
||||
unsigned long bits[], unsigned int type, size_t count)
|
||||
{
|
||||
void __iomem *addr = edev->addr;
|
||||
int i, j;
|
||||
@ -99,6 +99,7 @@ static void events_import_abs_params(struct event_dev *edev)
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(val); j++) {
|
||||
int offset = (i * ARRAY_SIZE(val) + j) * sizeof(u32);
|
||||
|
||||
val[j] = __raw_readl(edev->addr + REG_DATA + offset);
|
||||
}
|
||||
|
||||
@ -112,7 +113,7 @@ static int events_probe(struct platform_device *pdev)
|
||||
struct input_dev *input_dev;
|
||||
struct event_dev *edev;
|
||||
struct resource *res;
|
||||
unsigned keymapnamelen;
|
||||
unsigned int keymapnamelen;
|
||||
void __iomem *addr;
|
||||
int irq;
|
||||
int i;
|
||||
@ -150,7 +151,7 @@ static int events_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < keymapnamelen; i++)
|
||||
edev->name[i] = __raw_readb(edev->addr + REG_DATA + i);
|
||||
|
||||
pr_debug("events_probe() keymap=%s\n", edev->name);
|
||||
pr_debug("%s: keymap=%s\n", __func__, edev->name);
|
||||
|
||||
input_dev->name = edev->name;
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
|
@ -841,4 +841,14 @@ config INPUT_RAVE_SP_PWRBUTTON
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called rave-sp-pwrbutton.
|
||||
|
||||
config INPUT_SC27XX_VIBRA
|
||||
tristate "Spreadtrum sc27xx vibrator support"
|
||||
depends on MFD_SC27XX_PMIC || COMPILE_TEST
|
||||
select INPUT_FF_MEMLESS
|
||||
help
|
||||
This option enables support for Spreadtrum sc27xx vibrator driver.
|
||||
|
||||
To compile this driver as a module, choose M here. The module will
|
||||
be called sc27xx_vibra.
|
||||
|
||||
endif
|
||||
|
@ -66,6 +66,7 @@ obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o
|
||||
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
|
||||
obj-$(CONFIG_INPUT_RK805_PWRKEY) += rk805-pwrkey.o
|
||||
obj-$(CONFIG_INPUT_SC27XX_VIBRA) += sc27xx-vibra.o
|
||||
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
|
||||
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
|
||||
obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o
|
||||
|
154
drivers/input/misc/sc27xx-vibra.c
Normal file
154
drivers/input/misc/sc27xx-vibra.c
Normal file
@ -0,0 +1,154 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 Spreadtrum Communications Inc.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define CUR_DRV_CAL_SEL GENMASK(13, 12)
|
||||
#define SLP_LDOVIBR_PD_EN BIT(9)
|
||||
#define LDO_VIBR_PD BIT(8)
|
||||
|
||||
struct vibra_info {
|
||||
struct input_dev *input_dev;
|
||||
struct work_struct play_work;
|
||||
struct regmap *regmap;
|
||||
u32 base;
|
||||
u32 strength;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static void sc27xx_vibra_set(struct vibra_info *info, bool on)
|
||||
{
|
||||
if (on) {
|
||||
regmap_update_bits(info->regmap, info->base, LDO_VIBR_PD, 0);
|
||||
regmap_update_bits(info->regmap, info->base,
|
||||
SLP_LDOVIBR_PD_EN, 0);
|
||||
info->enabled = true;
|
||||
} else {
|
||||
regmap_update_bits(info->regmap, info->base, LDO_VIBR_PD,
|
||||
LDO_VIBR_PD);
|
||||
regmap_update_bits(info->regmap, info->base,
|
||||
SLP_LDOVIBR_PD_EN, SLP_LDOVIBR_PD_EN);
|
||||
info->enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
static int sc27xx_vibra_hw_init(struct vibra_info *info)
|
||||
{
|
||||
return regmap_update_bits(info->regmap, info->base, CUR_DRV_CAL_SEL, 0);
|
||||
}
|
||||
|
||||
static void sc27xx_vibra_play_work(struct work_struct *work)
|
||||
{
|
||||
struct vibra_info *info = container_of(work, struct vibra_info,
|
||||
play_work);
|
||||
|
||||
if (info->strength && !info->enabled)
|
||||
sc27xx_vibra_set(info, true);
|
||||
else if (info->strength == 0 && info->enabled)
|
||||
sc27xx_vibra_set(info, false);
|
||||
}
|
||||
|
||||
static int sc27xx_vibra_play(struct input_dev *input, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct vibra_info *info = input_get_drvdata(input);
|
||||
|
||||
info->strength = effect->u.rumble.weak_magnitude;
|
||||
schedule_work(&info->play_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sc27xx_vibra_close(struct input_dev *input)
|
||||
{
|
||||
struct vibra_info *info = input_get_drvdata(input);
|
||||
|
||||
cancel_work_sync(&info->play_work);
|
||||
if (info->enabled)
|
||||
sc27xx_vibra_set(info, false);
|
||||
}
|
||||
|
||||
static int sc27xx_vibra_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vibra_info *info;
|
||||
int error;
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
info->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!info->regmap) {
|
||||
dev_err(&pdev->dev, "failed to get vibrator regmap.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
error = device_property_read_u32(&pdev->dev, "reg", &info->base);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to get vibrator base address.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
info->input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!info->input_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate input device.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->input_dev->name = "sc27xx:vibrator";
|
||||
info->input_dev->id.version = 0;
|
||||
info->input_dev->close = sc27xx_vibra_close;
|
||||
|
||||
input_set_drvdata(info->input_dev, info);
|
||||
input_set_capability(info->input_dev, EV_FF, FF_RUMBLE);
|
||||
INIT_WORK(&info->play_work, sc27xx_vibra_play_work);
|
||||
info->enabled = false;
|
||||
|
||||
error = sc27xx_vibra_hw_init(info);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to initialize the vibrator.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_ff_create_memless(info->input_dev, NULL,
|
||||
sc27xx_vibra_play);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register vibrator to FF.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_register_device(info->input_dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register input device.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id sc27xx_vibra_of_match[] = {
|
||||
{ .compatible = "sprd,sc2731-vibrator", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sc27xx_vibra_of_match);
|
||||
|
||||
static struct platform_driver sc27xx_vibra_driver = {
|
||||
.driver = {
|
||||
.name = "sc27xx-vibrator",
|
||||
.of_match_table = sc27xx_vibra_of_match,
|
||||
},
|
||||
.probe = sc27xx_vibra_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(sc27xx_vibra_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Spreadtrum SC27xx Vibrator Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Xiaotong Lu <xiaotong.lu@spreadtrum.com>");
|
@ -3,6 +3,7 @@
|
||||
#
|
||||
config RMI4_CORE
|
||||
tristate "Synaptics RMI4 bus support"
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Say Y here if you want to support the Synaptics RMI4 bus. This is
|
||||
required for all RMI4 device support.
|
||||
|
@ -32,15 +32,15 @@ void rmi_2d_sensor_abs_process(struct rmi_2d_sensor *sensor,
|
||||
if (obj->type == RMI_2D_OBJECT_NONE)
|
||||
return;
|
||||
|
||||
if (axis_align->swap_axes)
|
||||
swap(obj->x, obj->y);
|
||||
|
||||
if (axis_align->flip_x)
|
||||
obj->x = sensor->max_x - obj->x;
|
||||
|
||||
if (axis_align->flip_y)
|
||||
obj->y = sensor->max_y - obj->y;
|
||||
|
||||
if (axis_align->swap_axes)
|
||||
swap(obj->x, obj->y);
|
||||
|
||||
/*
|
||||
* Here checking if X offset or y offset are specified is
|
||||
* redundant. We just add the offsets or clip the values.
|
||||
@ -120,15 +120,15 @@ void rmi_2d_sensor_rel_report(struct rmi_2d_sensor *sensor, int x, int y)
|
||||
x = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)x));
|
||||
y = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)y));
|
||||
|
||||
if (axis_align->swap_axes)
|
||||
swap(x, y);
|
||||
|
||||
if (axis_align->flip_x)
|
||||
x = min(RMI_2D_REL_POS_MAX, -x);
|
||||
|
||||
if (axis_align->flip_y)
|
||||
y = min(RMI_2D_REL_POS_MAX, -y);
|
||||
|
||||
if (axis_align->swap_axes)
|
||||
swap(x, y);
|
||||
|
||||
if (x || y) {
|
||||
input_report_rel(sensor->input, REL_X, x);
|
||||
input_report_rel(sensor->input, REL_Y, y);
|
||||
@ -141,17 +141,10 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor)
|
||||
struct input_dev *input = sensor->input;
|
||||
int res_x;
|
||||
int res_y;
|
||||
int max_x, max_y;
|
||||
int input_flags = 0;
|
||||
|
||||
if (sensor->report_abs) {
|
||||
if (sensor->axis_align.swap_axes) {
|
||||
swap(sensor->max_x, sensor->max_y);
|
||||
swap(sensor->axis_align.clip_x_low,
|
||||
sensor->axis_align.clip_y_low);
|
||||
swap(sensor->axis_align.clip_x_high,
|
||||
sensor->axis_align.clip_y_high);
|
||||
}
|
||||
|
||||
sensor->min_x = sensor->axis_align.clip_x_low;
|
||||
if (sensor->axis_align.clip_x_high)
|
||||
sensor->max_x = min(sensor->max_x,
|
||||
@ -163,14 +156,19 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor)
|
||||
sensor->axis_align.clip_y_high);
|
||||
|
||||
set_bit(EV_ABS, input->evbit);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, 0, sensor->max_x,
|
||||
0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, sensor->max_y,
|
||||
0, 0);
|
||||
|
||||
max_x = sensor->max_x;
|
||||
max_y = sensor->max_y;
|
||||
if (sensor->axis_align.swap_axes)
|
||||
swap(max_x, max_y);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_x, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_y, 0, 0);
|
||||
|
||||
if (sensor->x_mm && sensor->y_mm) {
|
||||
res_x = (sensor->max_x - sensor->min_x) / sensor->x_mm;
|
||||
res_y = (sensor->max_y - sensor->min_y) / sensor->y_mm;
|
||||
if (sensor->axis_align.swap_axes)
|
||||
swap(res_x, res_y);
|
||||
|
||||
input_abs_set_res(input, ABS_X, res_x);
|
||||
input_abs_set_res(input, ABS_Y, res_y);
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/rmi.h>
|
||||
@ -167,6 +169,39 @@ static inline void rmi_function_of_probe(struct rmi_function *fn)
|
||||
{}
|
||||
#endif
|
||||
|
||||
static struct irq_chip rmi_irq_chip = {
|
||||
.name = "rmi4",
|
||||
};
|
||||
|
||||
static int rmi_create_function_irq(struct rmi_function *fn,
|
||||
struct rmi_function_handler *handler)
|
||||
{
|
||||
struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
|
||||
int i, error;
|
||||
|
||||
for (i = 0; i < fn->num_of_irqs; i++) {
|
||||
set_bit(fn->irq_pos + i, fn->irq_mask);
|
||||
|
||||
fn->irq[i] = irq_create_mapping(drvdata->irqdomain,
|
||||
fn->irq_pos + i);
|
||||
|
||||
irq_set_chip_data(fn->irq[i], fn);
|
||||
irq_set_chip_and_handler(fn->irq[i], &rmi_irq_chip,
|
||||
handle_simple_irq);
|
||||
irq_set_nested_thread(fn->irq[i], 1);
|
||||
|
||||
error = devm_request_threaded_irq(&fn->dev, fn->irq[i], NULL,
|
||||
handler->attention, IRQF_ONESHOT,
|
||||
dev_name(&fn->dev), fn);
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "Error %d registering IRQ\n", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_function_probe(struct device *dev)
|
||||
{
|
||||
struct rmi_function *fn = to_rmi_function(dev);
|
||||
@ -178,7 +213,14 @@ static int rmi_function_probe(struct device *dev)
|
||||
|
||||
if (handler->probe) {
|
||||
error = handler->probe(fn);
|
||||
return error;
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (fn->num_of_irqs && handler->attention) {
|
||||
error = rmi_create_function_irq(fn, handler);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -230,12 +272,18 @@ err_put_device:
|
||||
|
||||
void rmi_unregister_function(struct rmi_function *fn)
|
||||
{
|
||||
int i;
|
||||
|
||||
rmi_dbg(RMI_DEBUG_CORE, &fn->dev, "Unregistering F%02X.\n",
|
||||
fn->fd.function_number);
|
||||
|
||||
device_del(&fn->dev);
|
||||
of_node_put(fn->dev.of_node);
|
||||
put_device(&fn->dev);
|
||||
|
||||
for (i = 0; i < fn->num_of_irqs; i++)
|
||||
irq_dispose_mapping(fn->irq[i]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,12 @@
|
||||
|
||||
struct rmi_device;
|
||||
|
||||
/*
|
||||
* The interrupt source count in the function descriptor can represent up to
|
||||
* 6 interrupt sources in the normal manner.
|
||||
*/
|
||||
#define RMI_FN_MAX_IRQS 6
|
||||
|
||||
/**
|
||||
* struct rmi_function - represents the implementation of an RMI4
|
||||
* function for a particular device (basically, a driver for that RMI4 function)
|
||||
@ -26,6 +32,7 @@ struct rmi_device;
|
||||
* @irq_pos: The position in the irq bitfield this function holds
|
||||
* @irq_mask: For convenience, can be used to mask IRQ bits off during ATTN
|
||||
* interrupt handling.
|
||||
* @irqs: assigned virq numbers (up to num_of_irqs)
|
||||
*
|
||||
* @node: entry in device's list of functions
|
||||
*/
|
||||
@ -36,6 +43,7 @@ struct rmi_function {
|
||||
struct list_head node;
|
||||
|
||||
unsigned int num_of_irqs;
|
||||
int irq[RMI_FN_MAX_IRQS];
|
||||
unsigned int irq_pos;
|
||||
unsigned long irq_mask[];
|
||||
};
|
||||
@ -76,7 +84,7 @@ struct rmi_function_handler {
|
||||
void (*remove)(struct rmi_function *fn);
|
||||
int (*config)(struct rmi_function *fn);
|
||||
int (*reset)(struct rmi_function *fn);
|
||||
int (*attention)(struct rmi_function *fn, unsigned long *irq_bits);
|
||||
irqreturn_t (*attention)(int irq, void *ctx);
|
||||
int (*suspend)(struct rmi_function *fn);
|
||||
int (*resume)(struct rmi_function *fn);
|
||||
};
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <uapi/linux/input.h>
|
||||
#include <linux/rmi.h>
|
||||
#include "rmi_bus.h"
|
||||
@ -127,28 +128,11 @@ static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void process_one_interrupt(struct rmi_driver_data *data,
|
||||
struct rmi_function *fn)
|
||||
{
|
||||
struct rmi_function_handler *fh;
|
||||
|
||||
if (!fn || !fn->dev.driver)
|
||||
return;
|
||||
|
||||
fh = to_rmi_function_handler(fn->dev.driver);
|
||||
if (fh->attention) {
|
||||
bitmap_and(data->fn_irq_bits, data->irq_status, fn->irq_mask,
|
||||
data->irq_count);
|
||||
if (!bitmap_empty(data->fn_irq_bits, data->irq_count))
|
||||
fh->attention(fn, data->fn_irq_bits);
|
||||
}
|
||||
}
|
||||
|
||||
static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
|
||||
{
|
||||
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
|
||||
struct device *dev = &rmi_dev->dev;
|
||||
struct rmi_function *entry;
|
||||
int i;
|
||||
int error;
|
||||
|
||||
if (!data)
|
||||
@ -173,16 +157,8 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
|
||||
*/
|
||||
mutex_unlock(&data->irq_mutex);
|
||||
|
||||
/*
|
||||
* It would be nice to be able to use irq_chip to handle these
|
||||
* nested IRQs. Unfortunately, most of the current customers for
|
||||
* this driver are using older kernels (3.0.x) that don't support
|
||||
* the features required for that. Once they've shifted to more
|
||||
* recent kernels (say, 3.3 and higher), this should be switched to
|
||||
* use irq_chip.
|
||||
*/
|
||||
list_for_each_entry(entry, &data->function_list, node)
|
||||
process_one_interrupt(data, entry);
|
||||
for_each_set_bit(i, data->irq_status, data->irq_count)
|
||||
handle_nested_irq(irq_find_mapping(data->irqdomain, i));
|
||||
|
||||
if (data->input)
|
||||
input_sync(data->input);
|
||||
@ -1000,9 +976,13 @@ EXPORT_SYMBOL_GPL(rmi_driver_resume);
|
||||
static int rmi_driver_remove(struct device *dev)
|
||||
{
|
||||
struct rmi_device *rmi_dev = to_rmi_device(dev);
|
||||
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
|
||||
|
||||
rmi_disable_irq(rmi_dev, false);
|
||||
|
||||
irq_domain_remove(data->irqdomain);
|
||||
data->irqdomain = NULL;
|
||||
|
||||
rmi_f34_remove_sysfs(rmi_dev);
|
||||
rmi_free_function_list(rmi_dev);
|
||||
|
||||
@ -1034,7 +1014,8 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
|
||||
{
|
||||
struct rmi_device *rmi_dev = data->rmi_dev;
|
||||
struct device *dev = &rmi_dev->dev;
|
||||
int irq_count;
|
||||
struct fwnode_handle *fwnode = rmi_dev->xport->dev->fwnode;
|
||||
int irq_count = 0;
|
||||
size_t size;
|
||||
int retval;
|
||||
|
||||
@ -1045,7 +1026,6 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
|
||||
* being accessed.
|
||||
*/
|
||||
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
|
||||
irq_count = 0;
|
||||
data->bootloader_mode = false;
|
||||
|
||||
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
|
||||
@ -1057,6 +1037,15 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
|
||||
if (data->bootloader_mode)
|
||||
dev_warn(dev, "Device in bootloader mode.\n");
|
||||
|
||||
/* Allocate and register a linear revmap irq_domain */
|
||||
data->irqdomain = irq_domain_create_linear(fwnode, irq_count,
|
||||
&irq_domain_simple_ops,
|
||||
data);
|
||||
if (!data->irqdomain) {
|
||||
dev_err(&rmi_dev->dev, "Failed to create IRQ domain\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->irq_count = irq_count;
|
||||
data->num_of_irq_regs = (data->irq_count + 7) / 8;
|
||||
|
||||
@ -1079,10 +1068,9 @@ int rmi_init_functions(struct rmi_driver_data *data)
|
||||
{
|
||||
struct rmi_device *rmi_dev = data->rmi_dev;
|
||||
struct device *dev = &rmi_dev->dev;
|
||||
int irq_count;
|
||||
int irq_count = 0;
|
||||
int retval;
|
||||
|
||||
irq_count = 0;
|
||||
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
|
||||
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
|
||||
if (retval < 0) {
|
||||
|
@ -681,9 +681,9 @@ static int rmi_f01_resume(struct rmi_function *fn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f01_attention(struct rmi_function *fn,
|
||||
unsigned long *irq_bits)
|
||||
static irqreturn_t rmi_f01_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
int error;
|
||||
u8 device_status;
|
||||
@ -692,7 +692,7 @@ static int rmi_f01_attention(struct rmi_function *fn,
|
||||
if (error) {
|
||||
dev_err(&fn->dev,
|
||||
"Failed to read device status: %d.\n", error);
|
||||
return error;
|
||||
return IRQ_RETVAL(error);
|
||||
}
|
||||
|
||||
if (RMI_F01_STATUS_BOOTLOADER(device_status))
|
||||
@ -704,11 +704,11 @@ static int rmi_f01_attention(struct rmi_function *fn,
|
||||
error = rmi_dev->driver->reset_handler(rmi_dev);
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "Device reset failed: %d\n", error);
|
||||
return error;
|
||||
return IRQ_RETVAL(error);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
struct rmi_function_handler rmi_f01_handler = {
|
||||
|
@ -244,8 +244,9 @@ static int rmi_f03_config(struct rmi_function *fn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
static irqreturn_t rmi_f03_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
|
||||
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
|
||||
@ -262,7 +263,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
/* First grab the data passed by the transport device */
|
||||
if (drvdata->attn_data.size < ob_len) {
|
||||
dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
memcpy(obs, drvdata->attn_data.data, ob_len);
|
||||
@ -277,7 +278,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
"%s: Failed to read F03 output buffers: %d\n",
|
||||
__func__, error);
|
||||
serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
|
||||
return error;
|
||||
return IRQ_RETVAL(error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +304,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
serio_interrupt(f03->serio, ob_data, serio_flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rmi_f03_remove(struct rmi_function *fn)
|
||||
|
@ -570,9 +570,7 @@ static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger)
|
||||
}
|
||||
|
||||
static void rmi_f11_finger_handler(struct f11_data *f11,
|
||||
struct rmi_2d_sensor *sensor,
|
||||
unsigned long *irq_bits, int num_irq_regs,
|
||||
int size)
|
||||
struct rmi_2d_sensor *sensor, int size)
|
||||
{
|
||||
const u8 *f_state = f11->data.f_state;
|
||||
u8 finger_state;
|
||||
@ -581,12 +579,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
|
||||
int rel_fingers;
|
||||
int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
|
||||
|
||||
int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask,
|
||||
num_irq_regs * 8);
|
||||
int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask,
|
||||
num_irq_regs * 8);
|
||||
|
||||
if (abs_bits) {
|
||||
if (sensor->report_abs) {
|
||||
if (abs_size > size)
|
||||
abs_fingers = size / RMI_F11_ABS_BYTES;
|
||||
else
|
||||
@ -604,19 +597,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
|
||||
rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i],
|
||||
finger_state, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (rel_bits) {
|
||||
if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
|
||||
rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
|
||||
else
|
||||
rel_fingers = sensor->nbr_fingers;
|
||||
|
||||
for (i = 0; i < rel_fingers; i++)
|
||||
rmi_f11_rel_pos_report(f11, i);
|
||||
}
|
||||
|
||||
if (abs_bits) {
|
||||
/*
|
||||
* the absolute part is made in 2 parts to allow the kernel
|
||||
* tracking to take place.
|
||||
@ -638,7 +619,16 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
|
||||
}
|
||||
|
||||
input_mt_sync_frame(sensor->input);
|
||||
} else if (sensor->report_rel) {
|
||||
if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
|
||||
rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
|
||||
else
|
||||
rel_fingers = sensor->nbr_fingers;
|
||||
|
||||
for (i = 0; i < rel_fingers; i++)
|
||||
rmi_f11_rel_pos_report(f11, i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int f11_2d_construct_data(struct f11_data *f11)
|
||||
@ -1275,8 +1265,9 @@ static int rmi_f11_config(struct rmi_function *fn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
static irqreturn_t rmi_f11_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
|
||||
struct f11_data *f11 = dev_get_drvdata(&fn->dev);
|
||||
@ -1302,13 +1293,12 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
data_base_addr, f11->sensor.data_pkt,
|
||||
f11->sensor.pkt_size);
|
||||
if (error < 0)
|
||||
return error;
|
||||
return IRQ_RETVAL(error);
|
||||
}
|
||||
|
||||
rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
|
||||
drvdata->num_of_irq_regs, valid_bytes);
|
||||
rmi_f11_finger_handler(f11, &f11->sensor, valid_bytes);
|
||||
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rmi_f11_resume(struct rmi_function *fn)
|
||||
|
@ -197,10 +197,10 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
|
||||
rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
|
||||
}
|
||||
|
||||
static int rmi_f12_attention(struct rmi_function *fn,
|
||||
unsigned long *irq_nr_regs)
|
||||
static irqreturn_t rmi_f12_attention(int irq, void *ctx)
|
||||
{
|
||||
int retval;
|
||||
struct rmi_function *fn = ctx;
|
||||
struct rmi_device *rmi_dev = fn->rmi_dev;
|
||||
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
|
||||
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
|
||||
@ -222,7 +222,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
|
||||
if (retval < 0) {
|
||||
dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
|
||||
retval);
|
||||
return retval;
|
||||
return IRQ_RETVAL(retval);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
|
||||
|
||||
input_mt_sync_frame(sensor->input);
|
||||
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rmi_f12_write_control_regs(struct rmi_function *fn)
|
||||
|
@ -122,8 +122,9 @@ static void rmi_f30_report_button(struct rmi_function *fn,
|
||||
}
|
||||
}
|
||||
|
||||
static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
static irqreturn_t rmi_f30_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct f30_data *f30 = dev_get_drvdata(&fn->dev);
|
||||
struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
|
||||
int error;
|
||||
@ -134,7 +135,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
if (drvdata->attn_data.size < f30->register_count) {
|
||||
dev_warn(&fn->dev,
|
||||
"F30 interrupted, but data is missing\n");
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
memcpy(f30->data_regs, drvdata->attn_data.data,
|
||||
f30->register_count);
|
||||
@ -147,7 +148,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
dev_err(&fn->dev,
|
||||
"%s: Failed to read F30 data registers: %d\n",
|
||||
__func__, error);
|
||||
return error;
|
||||
return IRQ_RETVAL(error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,7 +160,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
rmi_f03_commit_buttons(f30->f03);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rmi_f30_config(struct rmi_function *fn)
|
||||
|
@ -100,8 +100,9 @@ static int rmi_f34_command(struct f34_data *f34, u8 command,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
static irqreturn_t rmi_f34_attention(int irq, void *ctx)
|
||||
{
|
||||
struct rmi_function *fn = ctx;
|
||||
struct f34_data *f34 = dev_get_drvdata(&fn->dev);
|
||||
int ret;
|
||||
u8 status;
|
||||
@ -126,7 +127,7 @@ static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
|
||||
complete(&f34->v7.cmd_done);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
|
||||
|
@ -610,11 +610,6 @@ error:
|
||||
mutex_unlock(&f54->data_mutex);
|
||||
}
|
||||
|
||||
static int rmi_f54_attention(struct rmi_function *fn, unsigned long *irqbits)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_f54_config(struct rmi_function *fn)
|
||||
{
|
||||
struct rmi_driver *drv = fn->rmi_dev->driver;
|
||||
@ -756,6 +751,5 @@ struct rmi_function_handler rmi_f54_handler = {
|
||||
.func = 0x54,
|
||||
.probe = rmi_f54_probe,
|
||||
.config = rmi_f54_config,
|
||||
.attention = rmi_f54_attention,
|
||||
.remove = rmi_f54_remove,
|
||||
};
|
||||
|
@ -100,7 +100,7 @@ static inline bool input_is_mt_axis(int axis)
|
||||
return axis == ABS_MT_SLOT || input_is_mt_value(axis);
|
||||
}
|
||||
|
||||
void input_mt_report_slot_state(struct input_dev *dev,
|
||||
bool input_mt_report_slot_state(struct input_dev *dev,
|
||||
unsigned int tool_type, bool active);
|
||||
|
||||
void input_mt_report_finger_count(struct input_dev *dev, int count);
|
||||
|
@ -354,6 +354,8 @@ struct rmi_driver_data {
|
||||
struct mutex irq_mutex;
|
||||
struct input_dev *input;
|
||||
|
||||
struct irq_domain *irqdomain;
|
||||
|
||||
u8 pdt_props;
|
||||
|
||||
u8 num_rx_electrodes;
|
||||
|
Loading…
Reference in New Issue
Block a user