drivers/input/misc/twl6040-vibra.c
Source file repositories/reference/linux-study-clean/drivers/input/misc/twl6040-vibra.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/input/misc/twl6040-vibra.c- Extension
.c- Size
- 9561 bytes
- Lines
- 364
- Domain
- Driver Families
- Bucket
- drivers/input
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/platform_device.hlinux/of.hlinux/workqueue.hlinux/input.hlinux/mfd/twl6040.hlinux/slab.hlinux/delay.hlinux/regulator/consumer.h
Detected Declarations
struct vibra_infofunction twl6040_vib_irq_handlerfunction twl6040_vibra_enablefunction twl6040_vibra_disablefunction twl6040_vibra_codefunction twl6040_vibra_set_effectfunction vibra_play_workfunction vibra_playfunction twl6040_vibra_closefunction twl6040_vibra_suspendfunction twl6040_vibra_probe
Annotated Snippet
struct vibra_info {
struct device *dev;
struct input_dev *input_dev;
struct work_struct play_work;
int irq;
bool enabled;
int weak_speed;
int strong_speed;
int direction;
unsigned int vibldrv_res;
unsigned int vibrdrv_res;
unsigned int viblmotor_res;
unsigned int vibrmotor_res;
struct regulator_bulk_data supplies[TWL6040_NUM_SUPPLIES];
struct twl6040 *twl6040;
};
static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
{
struct vibra_info *info = data;
struct twl6040 *twl6040 = info->twl6040;
u8 status;
status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
if (status & TWL6040_VIBLOCDET) {
dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
TWL6040_VIBENA);
}
if (status & TWL6040_VIBROCDET) {
dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
TWL6040_VIBENA);
}
return IRQ_HANDLED;
}
static void twl6040_vibra_enable(struct vibra_info *info)
{
struct twl6040 *twl6040 = info->twl6040;
int ret;
ret = regulator_bulk_enable(ARRAY_SIZE(info->supplies), info->supplies);
if (ret) {
dev_err(info->dev, "failed to enable regulators %d\n", ret);
return;
}
twl6040_power(info->twl6040, 1);
if (twl6040_get_revid(twl6040) <= TWL6040_REV_ES1_1) {
/*
* ERRATA: Disable overcurrent protection for at least
* 3ms when enabling vibrator drivers to avoid false
* overcurrent detection
*/
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
TWL6040_VIBENA | TWL6040_VIBCTRL);
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
TWL6040_VIBENA | TWL6040_VIBCTRL);
usleep_range(3000, 3500);
}
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
TWL6040_VIBENA);
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
TWL6040_VIBENA);
info->enabled = true;
}
static void twl6040_vibra_disable(struct vibra_info *info)
{
struct twl6040 *twl6040 = info->twl6040;
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, 0x00);
twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, 0x00);
twl6040_power(info->twl6040, 0);
regulator_bulk_disable(ARRAY_SIZE(info->supplies), info->supplies);
info->enabled = false;
}
static u8 twl6040_vibra_code(int vddvib, int vibdrv_res, int motor_res,
Annotation
- Immediate include surface: `linux/module.h`, `linux/platform_device.h`, `linux/of.h`, `linux/workqueue.h`, `linux/input.h`, `linux/mfd/twl6040.h`, `linux/slab.h`, `linux/delay.h`.
- Detected declarations: `struct vibra_info`, `function twl6040_vib_irq_handler`, `function twl6040_vibra_enable`, `function twl6040_vibra_disable`, `function twl6040_vibra_code`, `function twl6040_vibra_set_effect`, `function vibra_play_work`, `function vibra_play`, `function twl6040_vibra_close`, `function twl6040_vibra_suspend`.
- Atlas domain: Driver Families / drivers/input.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.