// SPDX-License-Identifier: GPL-2.0-only /* * Panasonic HotKey and LCD brightness control driver * (C) 2004 Hiroshi Miura <miura@da-cha.org> * (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 <laforge@gnumonks.org> * * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte * *--------------------------------------------------------------------------- * * ChangeLog: * Aug.18, 2020 Kenneth Chan <kenneth.t.chan@gmail.com> * -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 <mato@kotelna.sk> * - add support for optical driver power in * Y and W series * * Sep.23, 2008 Harald Welte <laforge@gnumonks.org> * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to * drivers/misc/panasonic-laptop.c * * Jul.04, 2008 Harald Welte <laforge@gnumonks.org> * -v0.94 replace /proc interface with device attributes * support {set,get}keycode on th input device * * Jun.27, 2008 Harald Welte <laforge@gnumonks.org> * -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 <laforge@gnumonks.org> * -v0.91 merge with 2.6.24-rc6 ACPI changes * * Nov.04, 2006 Hiroshi Miura <miura@da-cha.org> * -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 <miura@da-cha.org> * -v0.8.4 follow to change keyinput structure * thanks Fabian Yamaguchi <fabs@cs.tu-berlin.de>, * Jacob Bower <jacob.bower@ic.ac.uk> and * Hiroshi Yokota for providing solutions. * * Oct.02, 2004 Hiroshi Miura <miura@da-cha.org> * -v0.8.2 merge code of YOKOTA Hiroshi * <yokota@netlab.is.tsukuba.ac.jp>. * Add sticky key mode interface. * Refactoring acpi_pcc_generate_keyinput(). * * Sep.15, 2004 Hiroshi Miura <miura@da-cha.org> * -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 <miura@da-cha.org> * -v0.7 Change proc interface functions using seq_file * facility as same as other ACPI drivers. * * Aug.28, 2004 Hiroshi Miura <miura@da-cha.org> * -v0.6.4 Fix a silly error with status checking * * Aug.25, 2004 Hiroshi Miura <miura@da-cha.org> * -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 <dbronaugh@linuxboxen.org> * -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 <dbronaugh@linuxboxen.org> * -v0.6.1 Fix a silly error with status checking * * Aug.20, 2004 David Bronaugh <dbronaugh@linuxboxen.org> * - 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 <miura@da-cha.org> * - v0.5 support LCD brightness control * based on the disclosed information by MEI. * * Jul.25, 2004 Hiroshi Miura <miura@da-cha.org> * - v0.4 first post version * add function to retrive SIFR * * Jul.24, 2004 Hiroshi Miura <miura@da-cha.org> * - v0.3 get proper status of hotkey * * Jul.22, 2004 Hiroshi Miura <miura@da-cha.org> * - v0.2 add HotKey handler * * Jul.17, 2004 Hiroshi Miura <miura@da-cha.org> * - v0.1 start from toshiba_acpi driver written by John Belmonte
*/
status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY,
NULL, &s); if (ACPI_SUCCESS(status)) return s; else {
pr_err("evaluation error HKEY.SQTY\n"); return -EINVAL;
}
}
staticint acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
{
acpi_status status; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *hkey = NULL; int i;
status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, NULL,
&buffer); if (ACPI_FAILURE(status)) {
pr_err("evaluation error HKEY.SINF\n"); return0;
}
hkey = buffer.pointer; if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
pr_err("Invalid HKEY.SINF\n");
status = AE_ERROR; goto end;
}
if (pcc->num_sifr < hkey->package.count) {
pr_err("SQTY reports bad SINF length SQTY: %lu SINF-pkg-count: %u\n",
pcc->num_sifr, hkey->package.count);
status = AE_ERROR; goto end;
}
for (i = 0; i < hkey->package.count; i++) { union acpi_object *element = &(hkey->package.elements[i]); if (likely(element->type == ACPI_TYPE_INTEGER)) {
pcc->sinf[i] = element->integer.value;
} else
pr_err("Invalid HKEY.SINF data\n");
}
pcc->sinf[hkey->package.count] = -1;
end:
kfree(buffer.pointer); return status == AE_OK;
}
/* 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 */
/* returns ACPI_SUCCESS if methods to control optical drive are present */
static acpi_status check_optd_present(void)
{
acpi_status status = AE_OK;
acpi_handle handle;
status = acpi_get_handle(NULL, "\\_SB.STAT", &handle); if (ACPI_FAILURE(status)) goto out;
status = acpi_get_handle(NULL, "\\_SB.FBAY", &handle); if (ACPI_FAILURE(status)) goto out;
status = acpi_get_handle(NULL, "\\_SB.CDDI", &handle); if (ACPI_FAILURE(status)) goto out;
out: return status;
}
/* get optical driver power state */
staticint get_optd_power_state(void)
{
acpi_status status; unsignedlonglong state; int result;
status = acpi_evaluate_integer(NULL, "\\_SB.STAT", NULL, &state); if (ACPI_FAILURE(status)) {
pr_err("evaluation error _SB.STAT\n");
result = -EIO; goto out;
} switch (state) { case0: /* power off */
result = 0; break; case0x0f: /* power on */
result = 1; break; default:
result = -EIO; break;
}
out: return result;
}
/* set optical drive power state */
staticint set_optd_power_state(int new_state)
{ int result;
acpi_status status;
result = get_optd_power_state(); if (result < 0) goto out; if (new_state == result) goto out;
switch (new_state) { case0: /* power off */ /* Call CDDR instead, since they both call the same method * while CDDI takes 1 arg and we are not quite sure what it is.
*/
status = acpi_evaluate_object(NULL, "\\_SB.CDDR", NULL, NULL); if (ACPI_FAILURE(status)) {
pr_err("evaluation error _SB.CDDR\n");
result = -EIO;
} break; case1: /* power on */
status = acpi_evaluate_object(NULL, "\\_SB.FBAY", NULL, NULL); if (ACPI_FAILURE(status)) {
pr_err("evaluation error _SB.FBAY\n");
result = -EIO;
} break; default:
result = -EINVAL; break;
}
key = result & GENMASK(6, 0);
updown = result & BIT(7); /* 0x80 == key down; 0x00 = key up */
/* hack: some firmware sends no key down for sleep / hibernate */ if (key == 7 || key == 10) { if (updown)
sleep_keydown_seen = 1; if (!sleep_keydown_seen)
sparse_keymap_report_event(hotk_input_dev,
key, 0x80, false);
}
/* * Don't report brightness key-presses if they are also reported * by the ACPI video bus.
*/ if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses()) return;
if (ACPI_SUCCESS(status)) {
status = acpi_install_notify_handler(handle,
ACPI_SYSTEM_NOTIFY,
pcc_optd_notify, pcc); if (ACPI_FAILURE(status))
pr_err("Failed to register notify on %s\n", node);
} else return -ENODEV;
/* * pcc->sinf is expected to at least have the AC+DC brightness entries. * Accesses to higher SINF entries are checked against num_sifr.
*/ if (num_sifr <= SINF_DC_CUR_BRIGHT || num_sifr > 255) {
pr_err("num_sifr %d out of range %d - 255\n", num_sifr, SINF_DC_CUR_BRIGHT + 1); return -ENODEV;
}
/* * Some DSDT-s have an off-by-one bug where the SINF package count is * one higher than the SQTY reported value, allocate 1 entry extra.
*/
num_sifr++;
pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL); if (!pcc) {
pr_err("Couldn't allocate mem for pcc"); return -ENOMEM;
}
pcc->sinf = kcalloc(num_sifr + 1, sizeof(u32), GFP_KERNEL); if (!pcc->sinf) {
result = -ENOMEM; goto out_hotkey;
}
pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
&pcc_backlight_ops, &props); if (IS_ERR(pcc->backlight)) {
result = PTR_ERR(pcc->backlight); goto out_input;
}
/* read the initial brightness setting from the hardware */
pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
}
/* Reset initial sticky key mode since the hardware register state is not consistent */
acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, 0);
pcc->sticky_key = 0;
pcc->ac_brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
pcc->dc_brightness = pcc->sinf[SINF_DC_CUR_BRIGHT]; if (pcc->num_sifr > SINF_MUTE)
pcc->mute = pcc->sinf[SINF_MUTE]; if (pcc->num_sifr > SINF_ECO_MODE)
pcc->eco_mode = pcc->sinf[SINF_ECO_MODE]; if (pcc->num_sifr > SINF_CUR_BRIGHT)
pcc->current_brightness = pcc->sinf[SINF_CUR_BRIGHT];
/* add sysfs attributes */
result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group); if (result) goto out_backlight;
/* optical drive initialization */ if (ACPI_SUCCESS(check_optd_present())) {
pcc->platform = platform_device_register_simple("panasonic",
PLATFORM_DEVID_NONE, NULL, 0); if (IS_ERR(pcc->platform)) {
result = PTR_ERR(pcc->platform); goto out_backlight;
}
result = device_create_file(&pcc->platform->dev,
&dev_attr_cdpower);
pcc_register_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD"); if (result) goto out_platform;
} else {
pcc->platform = NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.