Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

platform/x86: uniwill-laptop: Mark FN lock status as being volatile

It turns out that the FN lock status can be changed by the underlying
hardware when the user presses a special key combination. Mark the
associated register as volatile to prevent regmap from caching said
value. Also add the necessary suspend/resume handling.

Fixes: d050479693bb ("platform/x86: Add Uniwill laptop driver")
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20260218005101.73680-4-W_Armin@gmx.de
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Armin Wolf and committed by
Ilpo Järvinen
2be519d9 67e7eb4c

+35 -4
+35 -4
drivers/platform/x86/uniwill/uniwill-acpi.c
··· 330 330 struct acpi_battery_hook hook; 331 331 unsigned int last_charge_ctrl; 332 332 struct mutex battery_lock; /* Protects the list of currently registered batteries */ 333 + unsigned int last_status; 333 334 unsigned int last_switch_status; 334 335 struct mutex super_key_lock; /* Protects the toggling of the super key lock state */ 335 336 struct list_head batteries; ··· 581 580 case EC_ADDR_SECOND_FAN_RPM_1: 582 581 case EC_ADDR_SECOND_FAN_RPM_2: 583 582 case EC_ADDR_BAT_ALERT: 583 + case EC_ADDR_BIOS_OEM: 584 584 case EC_ADDR_PWM_1: 585 585 case EC_ADDR_PWM_2: 586 586 case EC_ADDR_TRIGGER: ··· 1510 1508 regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL); 1511 1509 } 1512 1510 1513 - static int uniwill_suspend_keyboard(struct uniwill_data *data) 1511 + static int uniwill_suspend_fn_lock(struct uniwill_data *data) 1512 + { 1513 + if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK)) 1514 + return 0; 1515 + 1516 + /* 1517 + * The EC_ADDR_BIOS_OEM is marked as volatile, so we have to restore it 1518 + * ourselves. 1519 + */ 1520 + return regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &data->last_status); 1521 + } 1522 + 1523 + static int uniwill_suspend_super_key(struct uniwill_data *data) 1514 1524 { 1515 1525 if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY)) 1516 1526 return 0; ··· 1561 1547 struct uniwill_data *data = dev_get_drvdata(dev); 1562 1548 int ret; 1563 1549 1564 - ret = uniwill_suspend_keyboard(data); 1550 + ret = uniwill_suspend_fn_lock(data); 1551 + if (ret < 0) 1552 + return ret; 1553 + 1554 + ret = uniwill_suspend_super_key(data); 1565 1555 if (ret < 0) 1566 1556 return ret; 1567 1557 ··· 1583 1565 return 0; 1584 1566 } 1585 1567 1586 - static int uniwill_resume_keyboard(struct uniwill_data *data) 1568 + static int uniwill_resume_fn_lock(struct uniwill_data *data) 1569 + { 1570 + if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK)) 1571 + return 0; 1572 + 1573 + return regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, 1574 + data->last_status); 1575 + } 1576 + 1577 + static int uniwill_resume_super_key(struct uniwill_data *data) 1587 1578 { 1588 1579 unsigned int value; 1589 1580 int ret; ··· 1640 1613 if (ret < 0) 1641 1614 return ret; 1642 1615 1643 - ret = uniwill_resume_keyboard(data); 1616 + ret = uniwill_resume_fn_lock(data); 1617 + if (ret < 0) 1618 + return ret; 1619 + 1620 + ret = uniwill_resume_super_key(data); 1644 1621 if (ret < 0) 1645 1622 return ret; 1646 1623