drivers/input/touchscreen/silead.c

Source file repositories/reference/linux-study-clean/drivers/input/touchscreen/silead.c

File Facts

System
Linux kernel
Corpus path
drivers/input/touchscreen/silead.c
Extension
.c
Size
22097 bytes
Lines
832
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 silead_ts_data {
	struct i2c_client *client;
	struct gpio_desc *gpio_power;
	struct input_dev *input;
	struct input_dev *pen_input;
	struct regulator_bulk_data regulators[2];
	char fw_name[64];
	struct touchscreen_properties prop;
	u32 chip_id;
	struct input_mt_pos pos[SILEAD_MAX_FINGERS];
	int slots[SILEAD_MAX_FINGERS];
	int id[SILEAD_MAX_FINGERS];
	u32 efi_fw_min_max[4];
	bool efi_fw_min_max_set;
	bool pen_supported;
	bool pen_down;
	u32 pen_x_res;
	u32 pen_y_res;
	int pen_up_count;
};

struct silead_fw_data {
	u32 offset;
	u32 val;
};

static void silead_apply_efi_fw_min_max(struct silead_ts_data *data)
{
	struct input_absinfo *absinfo_x = &data->input->absinfo[ABS_MT_POSITION_X];
	struct input_absinfo *absinfo_y = &data->input->absinfo[ABS_MT_POSITION_Y];

	if (!data->efi_fw_min_max_set)
		return;

	absinfo_x->minimum = data->efi_fw_min_max[0];
	absinfo_x->maximum = data->efi_fw_min_max[1];
	absinfo_y->minimum = data->efi_fw_min_max[2];
	absinfo_y->maximum = data->efi_fw_min_max[3];

	if (data->prop.invert_x) {
		absinfo_x->maximum -= absinfo_x->minimum;
		absinfo_x->minimum = 0;
	}

	if (data->prop.invert_y) {
		absinfo_y->maximum -= absinfo_y->minimum;
		absinfo_y->minimum = 0;
	}

	if (data->prop.swap_x_y) {
		swap(absinfo_x->minimum, absinfo_y->minimum);
		swap(absinfo_x->maximum, absinfo_y->maximum);
	}
}

static int silead_ts_request_input_dev(struct silead_ts_data *data)
{
	struct device *dev = &data->client->dev;
	int error;

	data->input = devm_input_allocate_device(dev);
	if (!data->input) {
		dev_err(dev,
			"Failed to allocate input device\n");
		return -ENOMEM;
	}

	input_set_abs_params(data->input, ABS_MT_POSITION_X, 0, 4095, 0, 0);
	input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
	touchscreen_parse_properties(data->input, true, &data->prop);
	silead_apply_efi_fw_min_max(data);

	input_mt_init_slots(data->input, SILEAD_MAX_FINGERS,
			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
			    INPUT_MT_TRACK);

	if (device_property_read_bool(dev, "silead,home-button"))
		input_set_capability(data->input, EV_KEY, KEY_LEFTMETA);

	data->input->name = SILEAD_TS_NAME;
	data->input->phys = "input/ts";
	data->input->id.bustype = BUS_I2C;

	error = input_register_device(data->input);
	if (error) {
		dev_err(dev, "Failed to register input device: %d\n", error);
			return error;
	}

	return 0;

Annotation

Implementation Notes