drivers/input/misc/pm8xxx-vibrator.c

Source file repositories/reference/linux-study-clean/drivers/input/misc/pm8xxx-vibrator.c

File Facts

System
Linux kernel
Corpus path
drivers/input/misc/pm8xxx-vibrator.c
Extension
.c
Size
7689 bytes
Lines
306
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pm8xxx_regs {
	unsigned int enable_offset;
	unsigned int enable_mask;

	unsigned int drv_offset;
	unsigned int drv_mask;
	unsigned int drv_shift;
	unsigned int drv2_offset;
	unsigned int drv2_mask;
	unsigned int drv2_shift;
	unsigned int drv_en_manual_mask;
	bool	     drv_in_step;
};

static const struct pm8xxx_regs pm8058_regs = {
	.drv_offset = 0,
	.drv_mask = GENMASK(7, 3),
	.drv_shift = 3,
	.drv_en_manual_mask = 0xfc,
	.drv_in_step = true,
};

static struct pm8xxx_regs pm8916_regs = {
	.enable_offset = 0x46,
	.enable_mask = BIT(7),
	.drv_offset = 0x41,
	.drv_mask = GENMASK(4, 0),
	.drv_shift = 0,
	.drv_en_manual_mask = 0,
	.drv_in_step = true,
};

static struct pm8xxx_regs pmi632_regs = {
	.enable_offset = 0x46,
	.enable_mask = BIT(7),
	.drv_offset = 0x40,
	.drv_mask = GENMASK(7, 0),
	.drv_shift = 0,
	.drv2_offset = 0x41,
	.drv2_mask = GENMASK(3, 0),
	.drv2_shift = 8,
	.drv_en_manual_mask = 0,
	.drv_in_step = false,
};

/**
 * struct pm8xxx_vib - structure to hold vibrator data
 * @vib_input_dev: input device supporting force feedback
 * @work: work structure to set the vibration parameters
 * @regmap: regmap for register read/write
 * @regs: registers' info
 * @enable_addr: vibrator enable register
 * @drv_addr: vibrator drive strength register
 * @drv2_addr: vibrator drive strength upper byte register
 * @speed: speed of vibration set from userland
 * @active: state of vibrator
 * @level: level of vibration to set in the chip
 * @reg_vib_drv: regs->drv_addr register value
 */
struct pm8xxx_vib {
	struct input_dev *vib_input_dev;
	struct work_struct work;
	struct regmap *regmap;
	const struct pm8xxx_regs *regs;
	unsigned int enable_addr;
	unsigned int drv_addr;
	unsigned int drv2_addr;
	int speed;
	int level;
	bool active;
	u8  reg_vib_drv;
};

/**
 * pm8xxx_vib_set - handler to start/stop vibration
 * @vib: pointer to vibrator structure
 * @on: state to set
 */
static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
{
	int rc;
	unsigned int val = vib->reg_vib_drv;
	const struct pm8xxx_regs *regs = vib->regs;

	if (regs->drv_in_step)
		vib->level /= VIB_PER_STEP_mV(vib);

	if (on)
		val |= (vib->level << regs->drv_shift) & regs->drv_mask;
	else

Annotation

Implementation Notes