drivers/platform/x86/lg-laptop.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/lg-laptop.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/lg-laptop.c
Extension
.c
Size
21178 bytes
Lines
913
Domain
Driver Families
Bucket
drivers/platform
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

if (eventcode == 0x10000000) {
			led_classdev_notify_brightness_hw_changed(
				&kbd_backlight, get_kbd_backlight_level(kbd_backlight.dev->parent));
		} else {
			key = sparse_keymap_entry_from_scancode(
				wmi_input_dev, eventcode);
			if (key && key->type == KE_KEY)
				sparse_keymap_report_entry(wmi_input_dev,
							   key, 1, true);
		}
	}

	pr_debug("Type: %i    Eventcode: 0x%llx\n", obj->type,
		 obj->integer.value);
}

static void wmi_input_setup(void)
{
	acpi_status status;

	wmi_input_dev = input_allocate_device();
	if (wmi_input_dev) {
		wmi_input_dev->name = "LG WMI hotkeys";
		wmi_input_dev->phys = "wmi/input0";
		wmi_input_dev->id.bustype = BUS_HOST;

		if (sparse_keymap_setup(wmi_input_dev, wmi_keymap, NULL) ||
		    input_register_device(wmi_input_dev)) {
			pr_info("Cannot initialize input device");
			input_free_device(wmi_input_dev);
			return;
		}

		inited |= INIT_SPARSE_KEYMAP;
		status = wmi_install_notify_handler(WMI_EVENT_GUID0, wmi_notify,
						    (void *)0);
		if (ACPI_SUCCESS(status))
			inited |= INIT_INPUT_WMI_0;

		status = wmi_install_notify_handler(WMI_EVENT_GUID2, wmi_notify,
						    (void *)2);
		if (ACPI_SUCCESS(status))
			inited |= INIT_INPUT_WMI_2;
	} else {
		pr_info("Cannot allocate input device");
	}
}

static ssize_t fan_mode_store(struct device *dev,
			      struct device_attribute *attr,
			      const char *buffer, size_t count)
{
	unsigned long value;
	union acpi_object *r;
	int ret;

	ret = kstrtoul(buffer, 10, &value);
	if (ret)
		return ret;
	if (value >= 3)
		return -EINVAL;

	r = lg_wmab(dev, WM_FAN_MODE, WM_SET,
		FIELD_PREP(FAN_MODE_LOWER, value) |
		FIELD_PREP(FAN_MODE_UPPER, value));
	kfree(r);

	return count;
}

static ssize_t fan_mode_show(struct device *dev,
			     struct device_attribute *attr, char *buffer)
{
	unsigned int mode;
	union acpi_object *r;

	r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0);
	if (!r)
		return -EIO;

	if (r->type != ACPI_TYPE_INTEGER) {
		kfree(r);
		return -EIO;
	}

	mode = FIELD_GET(FAN_MODE_LOWER, r->integer.value);
	kfree(r);

	return sysfs_emit(buffer, "%d\n", mode);
}

Annotation

Implementation Notes