drivers/input/mouse/synaptics_i2c.c

Source file repositories/reference/linux-study-clean/drivers/input/mouse/synaptics_i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/input/mouse/synaptics_i2c.c
Extension
.c
Size
16961 bytes
Lines
640
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 synaptics_i2c {
	struct i2c_client	*client;
	struct input_dev	*input;
	struct delayed_work	dwork;
	int			no_data_count;
	int			no_decel_param;
	int			reduce_report_param;
	int			no_filter_param;
	int			scan_rate_param;
	int			scan_ms;
};

static inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rate)
{
	touch->scan_ms = MSEC_PER_SEC / scan_rate;
	touch->scan_rate_param = scan_rate;
}

/*
 * Driver's initial design makes no race condition possible on i2c bus,
 * so there is no need in any locking.
 * Keep it in mind, while playing with the code.
 */
static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg)
{
	int error;

	error = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
	if (error)
		return error;

	return i2c_smbus_read_byte_data(client, reg & 0xff);
}

static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val)
{
	int error;

	error = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
	if (error)
		return error;

	error = i2c_smbus_write_byte_data(client, reg & 0xff, val);
	if (error)
		return error;

	return error;
}

static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg)
{
	int error;

	error = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8);
	if (error)
		return error;

	return i2c_smbus_read_word_data(client, reg & 0xff);
}

static int synaptics_i2c_config(struct i2c_client *client)
{
	int control;
	int error;
	u8 int_en;

	/* set Report Rate to Device Highest (>=80) and Sleep to normal */
	error = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1);
	if (error)
		return error;

	/* set Interrupt Disable to Func20 / Enable to Func10) */
	int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK;
	error = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en);
	if (error)
		return error;

	control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG);
	/* No Deceleration */
	control |= no_decel ? 1 << NO_DECELERATION : 0;
	/* Reduced Reporting */
	control |= reduce_report ? 1 << REDUCE_REPORTING : 0;
	/* No Filter */
	control |= no_filter ? 1 << NO_FILTER : 0;
	error = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control);
	if (error)
		return error;

	return 0;
}

Annotation

Implementation Notes