drivers/input/misc/aw86927.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/misc/aw86927.c
Extension
.c
Size
24608 bytes
Lines
883
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 aw86927_data {
	enum aw86927_model model;
	struct work_struct play_work;
	struct device *dev;
	struct input_dev *input_dev;
	struct i2c_client *client;
	struct regmap *regmap;
	struct gpio_desc *reset_gpio;
	u16 level;
};

static const struct regmap_config aw86927_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
	.cache_type = REGCACHE_NONE,
	.max_register = 0x80,
};

/*
 * Sine wave representing the magnitude of the drive to be used.
 * Data is encoded in two's complement.
 *   round(84 * sin(x / 16.25))
 */
static const u8 aw86927_waveform[] = {
	0x00, 0x05, 0x0a, 0x0f, 0x14, 0x1a, 0x1f, 0x23, 0x28, 0x2d, 0x31, 0x35,
	0x39, 0x3d, 0x41, 0x44, 0x47, 0x4a, 0x4c, 0x4f, 0x51, 0x52, 0x53, 0x54,
	0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x52, 0x51, 0x4f, 0x4d, 0x4a, 0x47,
	0x44, 0x41, 0x3d, 0x3a, 0x36, 0x31, 0x2d, 0x28, 0x24, 0x1f, 0x1a, 0x15,
	0x10, 0x0a, 0x05, 0x00, 0xfc, 0xf6, 0xf1, 0xec, 0xe7, 0xe2, 0xdd, 0xd8,
	0xd4, 0xcf, 0xcb, 0xc7, 0xc3, 0xbf, 0xbc, 0xb9, 0xb6, 0xb4, 0xb1, 0xb0,
	0xae, 0xad, 0xac, 0xab, 0xab, 0xab, 0xab, 0xab, 0xac, 0xae, 0xaf, 0xb1,
	0xb3, 0xb6, 0xb8, 0xbc, 0xbf, 0xc2, 0xc6, 0xca, 0xce, 0xd3, 0xd7, 0xdc,
	0xe1, 0xe6, 0xeb, 0xf0, 0xf5, 0xfb
};

struct aw86927_sram_waveform_header {
	u8 version;
	__be16 start_address;
	__be16 end_address;
} __packed;

static const struct aw86927_sram_waveform_header sram_waveform_header = {
	.version = 0x01,
	.start_address = cpu_to_be16(AW86927_RAM_BASE_ADDR +
			sizeof(struct aw86927_sram_waveform_header)),
	.end_address = cpu_to_be16(AW86927_RAM_BASE_ADDR +
			sizeof(struct aw86927_sram_waveform_header) +
			ARRAY_SIZE(aw86927_waveform) - 1),
};

static int aw86927_wait_enter_standby(struct aw86927_data *haptics)
{
	unsigned int reg_val;
	int err;

	err = regmap_read_poll_timeout(haptics->regmap, AW86927_GLBRD5_REG, reg_val,
				       (FIELD_GET(AW86927_GLBRD5_STATE_MASK, reg_val) ==
						AW86927_GLBRD5_STATE_STANDBY),
				       2500, 2500 * 100);

	if (err) {
		dev_err(haptics->dev, "did not enter standby: %d\n", err);
		return err;
	}
	return 0;
}

static int aw86927_play_mode(struct aw86927_data *haptics, u8 play_mode)
{
	int err;

	switch (play_mode) {
	case AW86927_STANDBY_MODE:
		/* Briefly toggle standby, then toggle back to standby off */
		err = regmap_update_bits(haptics->regmap,
					 AW86927_SYSCTRL3_REG,
					 AW86927_SYSCTRL3_STANDBY_MASK,
					 FIELD_PREP(AW86927_SYSCTRL3_STANDBY_MASK,
						    AW86927_SYSCTRL3_STANDBY_ON));
		if (err)
			return err;

		err = regmap_update_bits(haptics->regmap,
					 AW86927_SYSCTRL3_REG,
					 AW86927_SYSCTRL3_STANDBY_MASK,
					 FIELD_PREP(AW86927_SYSCTRL3_STANDBY_MASK,
						    AW86927_SYSCTRL3_STANDBY_OFF));
		if (err)
			return err;

Annotation

Implementation Notes