// SPDX-License-Identifier: GPL-2.0-only /* * Panasonic HotKey and LCD brightness control driver * (C) 2004 Hiroshi Miura <[email protected]> * (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/ * (C) YOKOTA Hiroshi <yokota (at) netlab. is. tsukuba. ac. jp> * (C) 2004 David Bronaugh <dbronaugh> * (C) 2006-2008 Harald Welte <[email protected]> * * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte * *--------------------------------------------------------------------------- * * ChangeLog: * Aug.18, 2020 Kenneth Chan <[email protected]> * -v0.98 add platform devices for firmware brightness registers * add support for battery charging threshold (eco mode) * resolve hotkey double trigger * add write support to mute * fix sticky_key init bug * fix naming of platform files for consistency with other * modules * split MODULE_AUTHOR() by one author per macro call * replace ACPI prints with pr_*() macros * -v0.97 add support for cdpower hardware switch * -v0.96 merge Lucina's enhancement * Jan.13, 2009 Martin Lucina <[email protected]> * - add support for optical driver power in * Y and W series * * Sep.23, 2008 Harald Welte <[email protected]> * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to * drivers/misc/panasonic-laptop.c * * Jul.04, 2008 Harald Welte <[email protected]> * -v0.94 replace /proc interface with device attributes * support {set,get}keycode on th input device * * Jun.27, 2008 Harald Welte <[email protected]> * -v0.92 merge with 2.6.26-rc6 input API changes * remove broken <= 2.6.15 kernel support * resolve all compiler warnings * various coding style fixes (checkpatch.pl) * add support for backlight api * major code restructuring * * Dac.28, 2007 Harald Welte <[email protected]> * -v0.91 merge with 2.6.24-rc6 ACPI changes * * Nov.04, 2006 Hiroshi Miura <[email protected]> * -v0.9 remove warning about section reference. * remove acpi_os_free * add /proc/acpi/pcc/brightness interface for HAL access * merge dbronaugh's enhancement * Aug.17, 2004 David Bronaugh (dbronaugh) * - Added screen brightness setting interface * Thanks to FreeBSD crew (acpi_panasonic.c) * for the ideas I needed to accomplish it * * May.29, 2006 Hiroshi Miura <[email protected]> * -v0.8.4 follow to change keyinput structure * thanks Fabian Yamaguchi <[email protected]>, * Jacob Bower <[email protected]> and * Hiroshi Yokota for providing solutions. * * Oct.02, 2004 Hiroshi Miura <[email protected]> * -v0.8.2 merge code of YOKOTA Hiroshi * <[email protected]>. * Add sticky key mode interface. * Refactoring acpi_pcc_generate_keyinput(). * * Sep.15, 2004 Hiroshi Miura <[email protected]> * -v0.8 Generate key input event on input subsystem. * This is based on yet another driver written by * Ryuta Nakanishi. * * Sep.10, 2004 Hiroshi Miura <[email protected]> * -v0.7 Change proc interface functions using seq_file * facility as same as other ACPI drivers. * * Aug.28, 2004 Hiroshi Miura <[email protected]> * -v0.6.4 Fix a silly error with status checking * * Aug.25, 2004 Hiroshi Miura <[email protected]> * -v0.6.3 replace read_acpi_int by standard function * acpi_evaluate_integer * some clean up and make smart copyright notice. * fix return value of pcc_acpi_get_key() * fix checking return value of acpi_bus_register_driver() * * Aug.22, 2004 David Bronaugh <[email protected]> * -v0.6.2 Add check on ACPI data (num_sifr) * Coding style cleanups, better error messages/handling * Fixed an off-by-one error in memory allocation * * Aug.21, 2004 David Bronaugh <[email protected]> * -v0.6.1 Fix a silly error with status checking * * Aug.20, 2004 David Bronaugh <[email protected]> * - v0.6 Correct brightness controls to reflect reality * based on information gleaned by Hiroshi Miura * and discussions with Hiroshi Miura * * Aug.10, 2004 Hiroshi Miura <[email protected]> * - v0.5 support LCD brightness control * based on the disclosed information by MEI. * * Jul.25, 2004 Hiroshi Miura <[email protected]> * - v0.4 first post version * add function to retrive SIFR * * Jul.24, 2004 Hiroshi Miura <[email protected]> * - v0.3 get proper status of hotkey * * Jul.22, 2004 Hiroshi Miura <[email protected]> * - v0.2 add HotKey handler * * Jul.17, 2004 Hiroshi Miura <[email protected]> * - v0.1 start from toshiba_acpi driver written by John Belmonte */ #include <linux/acpi.h> #include <linux/backlight.h> #include <linux/bits.h> #include <linux/ctype.h> #include <linux/i8042.h> #include <linux/init.h> #include <linux/input.h> #include <linux/input/sparse-keymap.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/seq_file.h> #include <linux/serio.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/uaccess.h> #include <acpi/video.h> MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; #define LOGPREFIX … /* Define ACPI PATHs */ /* Lets note hotkeys */ #define METHOD_HKEY_QUERY … #define METHOD_HKEY_SQTY … #define METHOD_HKEY_SINF … #define METHOD_HKEY_SSET … #define METHOD_ECWR … #define HKEY_NOTIFY … #define ECO_MODE_OFF … #define ECO_MODE_ON … #define ACPI_PCC_DRIVER_NAME … #define ACPI_PCC_DEVICE_NAME … #define ACPI_PCC_CLASS … #define ACPI_PCC_INPUT_PHYS … /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent ECO_MODEs: 0x03 = off, 0x83 = on */ enum SINF_BITS { … }; /* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */ static int acpi_pcc_hotkey_add(struct acpi_device *device); static void acpi_pcc_hotkey_remove(struct acpi_device *device); static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id pcc_device_ids[] = …; MODULE_DEVICE_TABLE(acpi, pcc_device_ids); #ifdef CONFIG_PM_SLEEP static int acpi_pcc_hotkey_resume(struct device *dev); #endif static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume); static struct acpi_driver acpi_pcc_driver = …; static const struct key_entry panasonic_keymap[] = …; struct pcc_acpi { … }; /* * On some Panasonic models the volume up / down / mute keys send duplicate * keypress events over the PS/2 kbd interface, filter these out. */ static bool panasonic_i8042_filter(unsigned char data, unsigned char str, struct serio *port) { … } /* method access functions */ static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val) { … } static inline int acpi_pcc_get_sqty(struct acpi_device *device) { … } static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc) { … } /* backlight API interface functions */ /* This driver currently treats AC and DC brightness identical, * since we don't need to invent an interface to the core ACPI * logic to receive events in case a power supply is plugged in * or removed */ static int bl_get(struct backlight_device *bd) { … } static int bl_set_status(struct backlight_device *bd) { … } static const struct backlight_ops pcc_backlight_ops = …; /* returns ACPI_SUCCESS if methods to control optical drive are present */ static acpi_status check_optd_present(void) { … } /* get optical driver power state */ static int get_optd_power_state(void) { … } /* set optical drive power state */ static int set_optd_power_state(int new_state) { … } /* sysfs user interface functions */ static ssize_t numbatt_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t lcdtype_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t mute_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t mute_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t sticky_key_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t sticky_key_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t eco_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t eco_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t ac_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t ac_brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t dc_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t dc_brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t current_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t current_brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t cdpower_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t cdpower_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static DEVICE_ATTR_RO(numbatt); static DEVICE_ATTR_RO(lcdtype); static DEVICE_ATTR_RW(mute); static DEVICE_ATTR_RW(sticky_key); static DEVICE_ATTR_RW(eco_mode); static DEVICE_ATTR_RW(ac_brightness); static DEVICE_ATTR_RW(dc_brightness); static DEVICE_ATTR_RW(current_brightness); static DEVICE_ATTR_RW(cdpower); static umode_t pcc_sysfs_is_visible(struct kobject *kobj, struct attribute *attr, int idx) { … } static struct attribute *pcc_sysfs_entries[] = …; static const struct attribute_group pcc_attr_group = …; /* hotkey input device driver */ static int sleep_keydown_seen; static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) { … } static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) { … } static void pcc_optd_notify(acpi_handle handle, u32 event, void *data) { … } static int pcc_register_optd_notifier(struct pcc_acpi *pcc, char *node) { … } static void pcc_unregister_optd_notifier(struct pcc_acpi *pcc, char *node) { … } static int acpi_pcc_init_input(struct pcc_acpi *pcc) { … } /* kernel module interface */ #ifdef CONFIG_PM_SLEEP static int acpi_pcc_hotkey_resume(struct device *dev) { … } #endif static int acpi_pcc_hotkey_add(struct acpi_device *device) { … } static void acpi_pcc_hotkey_remove(struct acpi_device *device) { … } module_acpi_driver(…) …;