mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'platform-drivers-x86-v6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Hans de Goede:
- AMD Platform Management Framework (PMF) driver with AMT and QnQF
support
- AMD PMC: Improved logging for debugging s2idle issues
- Big refactor of the ACPI/x86 backlight handling, ensuring that we
only register 1 /sys/class/backlight device per LCD panel
- Microsoft Surface:
- Surface Laptop Go 2 support
- Surface Pro 8 HID sensor support
- Asus WMI:
- Lots of cleanups
- Support for TUF RGB keyboard backlight control
- Add support for ROG X13 tablet mode
- Siemens Simatic: IPC227G and IPC427G support
- Toshiba ACPI laptop driver: Fan hwmon and battery ECO mode support
- tools/power/x86/intel-speed-select: Various improvements
- Various cleanups
- Various small bugfixes
* tag 'platform-drivers-x86-v6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (153 commits)
platform/x86: use PLATFORM_DEVID_NONE instead of -1
platform/x86/amd: pmc: Dump idle mask during "check" stage instead
platform/x86/intel/wmi: thunderbolt: Use dev_groups callback
platform/x86/amd: pmc: remove CONFIG_DEBUG_FS checks
platform/surface: Split memcpy() of struct ssam_event flexible array
platform/x86: compal-laptop: Get rid of a few forward declarations
platform/x86: intel-uncore-freq: Use sysfs_emit() to instead of scnprintf()
platform/x86: dell-smbios-base: Use sysfs_emit()
platform/x86/amd/pmf: Remove unused power_delta instances
platform/x86/amd/pmf: install notify handler after acpi init
Documentation/ABI/testing/sysfs-amd-pmf: Add ABI doc for AMD PMF
platform/x86/amd/pmf: Add sysfs to toggle CnQF
platform/x86/amd/pmf: Add support for CnQF
platform/x86/amd: pmc: Fix build without debugfs
platform/x86: hp-wmi: Support touchpad on/off
platform/x86: int3472/discrete: Drop a forward declaration
platform/x86: toshiba_acpi: change turn_on_panel_on_resume to static
platform/x86: wmi: Drop forward declaration of static functions
platform/x86: toshiba_acpi: Remove duplicate include
platform/x86: msi-laptop: Change DMI match / alias strings to fix module autoloading
...
This commit is contained in:
13
Documentation/ABI/testing/sysfs-amd-pmc
Normal file
13
Documentation/ABI/testing/sysfs-amd-pmc
Normal file
@@ -0,0 +1,13 @@
|
||||
What: /sys/bus/platform/drivers/amd_pmc/*/smu_fw_version
|
||||
Date: October 2022
|
||||
Contact: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Description: Reading this file reports the version of the firmware loaded to
|
||||
System Management Unit (SMU) contained in AMD CPUs and
|
||||
APUs.
|
||||
|
||||
What: /sys/bus/platform/drivers/amd_pmc/*/smu_program
|
||||
Date: October 2022
|
||||
Contact: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Description: Reading this file reports the program corresponding to the SMU
|
||||
firmware version. The program field is used to disambiguate two
|
||||
APU/CPU models that can share the same firmware binary.
|
||||
13
Documentation/ABI/testing/sysfs-amd-pmf
Normal file
13
Documentation/ABI/testing/sysfs-amd-pmf
Normal file
@@ -0,0 +1,13 @@
|
||||
What: /sys/devices/platform/*/cnqf_enable
|
||||
Date: September 2022
|
||||
Contact: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
|
||||
Description: Reading this file tells if the AMD Platform Management(PMF)
|
||||
Cool n Quiet Framework(CnQF) feature is enabled or not.
|
||||
|
||||
This feature is not enabled by default and gets only turned on
|
||||
if OEM BIOS passes a "flag" to PMF ACPI function (index 11 or 12)
|
||||
or in case the user writes "on".
|
||||
|
||||
To turn off CnQF user can write "off" to the sysfs node.
|
||||
Note: Systems that support auto mode will not have this sysfs file
|
||||
available.
|
||||
@@ -364,7 +364,10 @@ Date: April 2019
|
||||
Contact: linux-pm@vger.kernel.org
|
||||
Description:
|
||||
Represents a battery percentage level, above which charging will
|
||||
stop.
|
||||
stop. Not all hardware is capable of setting this to an arbitrary
|
||||
percentage. Drivers will round written values to the nearest
|
||||
supported value. Reading back the value will show the actual
|
||||
threshold set by the driver.
|
||||
|
||||
Access: Read, Write
|
||||
|
||||
|
||||
@@ -57,3 +57,44 @@ Description:
|
||||
* 0 - default,
|
||||
* 1 - overboost,
|
||||
* 2 - silent
|
||||
|
||||
What: /sys/devices/platform/<platform>/gpu_mux_mode
|
||||
Date: Aug 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: "Luke Jones" <luke@ljones.dev>
|
||||
Description:
|
||||
Switch the GPU hardware MUX mode. Laptops with this feature can
|
||||
can be toggled to boot with only the dGPU (discrete mode) or in
|
||||
standard Optimus/Hybrid mode. On switch a reboot is required:
|
||||
|
||||
* 0 - Discrete GPU,
|
||||
* 1 - Optimus/Hybrid,
|
||||
|
||||
What: /sys/devices/platform/<platform>/dgpu_disable
|
||||
Date: Aug 2022
|
||||
KernelVersion: 5.17
|
||||
Contact: "Luke Jones" <luke@ljones.dev>
|
||||
Description:
|
||||
Disable discrete GPU:
|
||||
* 0 - Enable dGPU,
|
||||
* 1 - Disable dGPU
|
||||
|
||||
What: /sys/devices/platform/<platform>/egpu_enable
|
||||
Date: Aug 2022
|
||||
KernelVersion: 5.17
|
||||
Contact: "Luke Jones" <luke@ljones.dev>
|
||||
Description:
|
||||
Enable the external GPU paired with ROG X-Flow laptops.
|
||||
Toggling this setting will also trigger ACPI to disable the dGPU:
|
||||
|
||||
* 0 - Disable,
|
||||
* 1 - Enable
|
||||
|
||||
What: /sys/devices/platform/<platform>/panel_od
|
||||
Date: Aug 2022
|
||||
KernelVersion: 5.17
|
||||
Contact: "Luke Jones" <luke@ljones.dev>
|
||||
Description:
|
||||
Enable an LCD response-time boost to reduce or remove ghosting:
|
||||
* 0 - Disable,
|
||||
* 1 - Enable
|
||||
|
||||
@@ -715,6 +715,74 @@ Contact: Sam Ravnborg
|
||||
|
||||
Level: Advanced
|
||||
|
||||
Brightness handling on devices with multiple internal panels
|
||||
============================================================
|
||||
|
||||
On x86/ACPI devices there can be multiple backlight firmware interfaces:
|
||||
(ACPI) video, vendor specific and others. As well as direct/native (PWM)
|
||||
register programming by the KMS driver.
|
||||
|
||||
To deal with this backlight drivers used on x86/ACPI call
|
||||
acpi_video_get_backlight_type() which has heuristics (+quirks) to select
|
||||
which backlight interface to use; and backlight drivers which do not match
|
||||
the returned type will not register themselves, so that only one backlight
|
||||
device gets registered (in a single GPU setup, see below).
|
||||
|
||||
At the moment this more or less assumes that there will only
|
||||
be 1 (internal) panel on a system.
|
||||
|
||||
On systems with 2 panels this may be a problem, depending on
|
||||
what interface acpi_video_get_backlight_type() selects:
|
||||
|
||||
1. native: in this case the KMS driver is expected to know which backlight
|
||||
device belongs to which output so everything should just work.
|
||||
2. video: this does support controlling multiple backlights, but some work
|
||||
will need to be done to get the output <-> backlight device mapping
|
||||
|
||||
The above assumes both panels will require the same backlight interface type.
|
||||
Things will break on systems with multiple panels where the 2 panels need
|
||||
a different type of control. E.g. one panel needs ACPI video backlight control,
|
||||
where as the other is using native backlight control. Currently in this case
|
||||
only one of the 2 required backlight devices will get registered, based on
|
||||
the acpi_video_get_backlight_type() return value.
|
||||
|
||||
If this (theoretical) case ever shows up, then supporting this will need some
|
||||
work. A possible solution here would be to pass a device and connector-name
|
||||
to acpi_video_get_backlight_type() so that it can deal with this.
|
||||
|
||||
Note in a way we already have a case where userspace sees 2 panels,
|
||||
in dual GPU laptop setups with a mux. On those systems we may see
|
||||
either 2 native backlight devices; or 2 native backlight devices.
|
||||
|
||||
Userspace already has code to deal with this by detecting if the related
|
||||
panel is active (iow which way the mux between the GPU and the panels
|
||||
points) and then uses that backlight device. Userspace here very much
|
||||
assumes a single panel though. It picks only 1 of the 2 backlight devices
|
||||
and then only uses that one.
|
||||
|
||||
Note that all userspace code (that I know off) is currently hardcoded
|
||||
to assume a single panel.
|
||||
|
||||
Before the recent changes to not register multiple (e.g. video + native)
|
||||
/sys/class/backlight devices for a single panel (on a single GPU laptop),
|
||||
userspace would see multiple backlight devices all controlling the same
|
||||
backlight.
|
||||
|
||||
To deal with this userspace had to always picks one preferred device under
|
||||
/sys/class/backlight and will ignore the others. So to support brightness
|
||||
control on multiple panels userspace will need to be updated too.
|
||||
|
||||
There are plans to allow brightness control through the KMS API by adding
|
||||
a "display brightness" property to drm_connector objects for panels. This
|
||||
solves a number of issues with the /sys/class/backlight API, including not
|
||||
being able to map a sysfs backlight device to a specific connector. Any
|
||||
userspace changes to add support for brightness control on devices with
|
||||
multiple panels really should build on top of this new KMS property.
|
||||
|
||||
Contact: Hans de Goede
|
||||
|
||||
Level: Advanced
|
||||
|
||||
Outside DRM
|
||||
===========
|
||||
|
||||
|
||||
@@ -1027,6 +1027,13 @@ L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/platform/x86/amd/pmc.c
|
||||
|
||||
AMD PMF DRIVER
|
||||
M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-amd-pmf
|
||||
F: drivers/platform/x86/amd/pmf/
|
||||
|
||||
AMD HSMP DRIVER
|
||||
M: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
|
||||
R: Carlos Bilbao <carlos.bilbao@amd.com>
|
||||
@@ -14542,6 +14549,7 @@ M: Daniel Dadap <ddadap@nvidia.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/platform/x86/nvidia-wmi-ec-backlight.c
|
||||
F: include/linux/platform_data/x86/nvidia-wmi-ec-backlight.h
|
||||
|
||||
NVM EXPRESS DRIVER
|
||||
M: Keith Busch <kbusch@kernel.org>
|
||||
|
||||
@@ -209,6 +209,7 @@ config ACPI_VIDEO
|
||||
tristate "Video"
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
depends on INPUT
|
||||
depends on ACPI_WMI || !X86
|
||||
select THERMAL
|
||||
help
|
||||
This driver implements the ACPI Extensions For Display Adapters
|
||||
|
||||
@@ -47,9 +47,6 @@ module_param(brightness_switch_enabled, bool, 0644);
|
||||
static bool allow_duplicates;
|
||||
module_param(allow_duplicates, bool, 0644);
|
||||
|
||||
static int disable_backlight_sysfs_if = -1;
|
||||
module_param(disable_backlight_sysfs_if, int, 0444);
|
||||
|
||||
#define REPORT_OUTPUT_KEY_EVENTS 0x01
|
||||
#define REPORT_BRIGHTNESS_KEY_EVENTS 0x02
|
||||
static int report_key_events = -1;
|
||||
@@ -73,6 +70,16 @@ module_param(device_id_scheme, bool, 0444);
|
||||
static int only_lcd = -1;
|
||||
module_param(only_lcd, int, 0444);
|
||||
|
||||
/*
|
||||
* Display probing is known to take up to 5 seconds, so delay the fallback
|
||||
* backlight registration by 5 seconds + 3 seconds for some extra margin.
|
||||
*/
|
||||
static int register_backlight_delay = 8;
|
||||
module_param(register_backlight_delay, int, 0444);
|
||||
MODULE_PARM_DESC(register_backlight_delay,
|
||||
"Delay in seconds before doing fallback (non GPU driver triggered) "
|
||||
"backlight registration, set to 0 to disable.");
|
||||
|
||||
static bool may_report_brightness_keys;
|
||||
static int register_count;
|
||||
static DEFINE_MUTEX(register_count_mutex);
|
||||
@@ -81,7 +88,9 @@ static LIST_HEAD(video_bus_head);
|
||||
static int acpi_video_bus_add(struct acpi_device *device);
|
||||
static int acpi_video_bus_remove(struct acpi_device *device);
|
||||
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
|
||||
void acpi_video_detect_exit(void);
|
||||
static void acpi_video_bus_register_backlight_work(struct work_struct *ignored);
|
||||
static DECLARE_DELAYED_WORK(video_bus_register_backlight_work,
|
||||
acpi_video_bus_register_backlight_work);
|
||||
|
||||
/*
|
||||
* Indices in the _BCL method response: the first two items are special,
|
||||
@@ -382,14 +391,6 @@ static int video_set_bqc_offset(const struct dmi_system_id *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_disable_backlight_sysfs_if(
|
||||
const struct dmi_system_id *d)
|
||||
{
|
||||
if (disable_backlight_sysfs_if == -1)
|
||||
disable_backlight_sysfs_if = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_set_device_id_scheme(const struct dmi_system_id *d)
|
||||
{
|
||||
device_id_scheme = true;
|
||||
@@ -462,56 +463,6 @@ static const struct dmi_system_id video_dmi_table[] = {
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* Some machines have a broken acpi-video interface for brightness
|
||||
* control, but still need an acpi_video_device_lcd_set_level() call
|
||||
* on resume to turn the backlight power on. We Enable backlight
|
||||
* control on these systems, but do not register a backlight sysfs
|
||||
* as brightness control does not work.
|
||||
*/
|
||||
{
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
|
||||
.callback = video_disable_backlight_sysfs_if,
|
||||
.ident = "Toshiba Portege R700",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R700"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugs.freedesktop.org/show_bug.cgi?id=82634 */
|
||||
.callback = video_disable_backlight_sysfs_if,
|
||||
.ident = "Toshiba Portege R830",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R830"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
|
||||
.callback = video_disable_backlight_sysfs_if,
|
||||
.ident = "Toshiba Satellite R830",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE R830"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_disable_backlight_sysfs_if,
|
||||
.ident = "Toshiba Satellite Z830",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE Z830"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_disable_backlight_sysfs_if,
|
||||
.ident = "Toshiba Portege Z830",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE Z830"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set
|
||||
* but the IDs actually follow the Device ID Scheme.
|
||||
@@ -1774,9 +1725,6 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
|
||||
if (result)
|
||||
return;
|
||||
|
||||
if (disable_backlight_sysfs_if > 0)
|
||||
return;
|
||||
|
||||
name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
|
||||
if (!name)
|
||||
return;
|
||||
@@ -1875,8 +1823,6 @@ static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
|
||||
if (video->backlight_registered)
|
||||
return 0;
|
||||
|
||||
acpi_video_run_bcl_for_osi(video);
|
||||
|
||||
if (acpi_video_get_backlight_type() != acpi_backlight_video)
|
||||
return 0;
|
||||
|
||||
@@ -2102,7 +2048,11 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
list_add_tail(&video->entry, &video_bus_head);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
acpi_video_bus_register_backlight(video);
|
||||
/*
|
||||
* The userspace visible backlight_device gets registered separately
|
||||
* from acpi_video_register_backlight().
|
||||
*/
|
||||
acpi_video_run_bcl_for_osi(video);
|
||||
acpi_video_bus_add_notify_handler(video);
|
||||
|
||||
return 0;
|
||||
@@ -2127,20 +2077,25 @@ static int acpi_video_bus_remove(struct acpi_device *device)
|
||||
|
||||
video = acpi_driver_data(device);
|
||||
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
acpi_video_bus_put_devices(video);
|
||||
|
||||
mutex_lock(&video_list_lock);
|
||||
list_del(&video->entry);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
acpi_video_bus_put_devices(video);
|
||||
|
||||
kfree(video->attached_array);
|
||||
kfree(video);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_video_bus_register_backlight_work(struct work_struct *ignored)
|
||||
{
|
||||
acpi_video_register_backlight();
|
||||
}
|
||||
|
||||
static int __init is_i740(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->device == 0x00D1)
|
||||
@@ -2251,6 +2206,18 @@ int acpi_video_register(void)
|
||||
*/
|
||||
register_count = 1;
|
||||
|
||||
/*
|
||||
* acpi_video_bus_add() skips registering the userspace visible
|
||||
* backlight_device. The intend is for this to be registered by the
|
||||
* drm/kms driver calling acpi_video_register_backlight() *after* it is
|
||||
* done setting up its own native backlight device. The delayed work
|
||||
* ensures that acpi_video_register_backlight() always gets called
|
||||
* eventually, in case there is no drm/kms driver or it is disabled.
|
||||
*/
|
||||
if (register_backlight_delay)
|
||||
schedule_delayed_work(&video_bus_register_backlight_work,
|
||||
register_backlight_delay * HZ);
|
||||
|
||||
leave:
|
||||
mutex_unlock(®ister_count_mutex);
|
||||
return ret;
|
||||
@@ -2261,6 +2228,7 @@ void acpi_video_unregister(void)
|
||||
{
|
||||
mutex_lock(®ister_count_mutex);
|
||||
if (register_count) {
|
||||
cancel_delayed_work_sync(&video_bus_register_backlight_work);
|
||||
acpi_bus_unregister_driver(&acpi_video_bus);
|
||||
register_count = 0;
|
||||
may_report_brightness_keys = false;
|
||||
@@ -2269,19 +2237,16 @@ void acpi_video_unregister(void)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_unregister);
|
||||
|
||||
void acpi_video_unregister_backlight(void)
|
||||
void acpi_video_register_backlight(void)
|
||||
{
|
||||
struct acpi_video_bus *video;
|
||||
|
||||
mutex_lock(®ister_count_mutex);
|
||||
if (register_count) {
|
||||
mutex_lock(&video_list_lock);
|
||||
list_for_each_entry(video, &video_bus_head, entry)
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
mutex_unlock(&video_list_lock);
|
||||
}
|
||||
mutex_unlock(®ister_count_mutex);
|
||||
mutex_lock(&video_list_lock);
|
||||
list_for_each_entry(video, &video_bus_head, entry)
|
||||
acpi_video_bus_register_backlight(video);
|
||||
mutex_unlock(&video_list_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_register_backlight);
|
||||
|
||||
bool acpi_video_handles_brightness_key_presses(void)
|
||||
{
|
||||
@@ -2318,7 +2283,6 @@ static int __init acpi_video_init(void)
|
||||
|
||||
static void __exit acpi_video_exit(void)
|
||||
{
|
||||
acpi_video_detect_exit();
|
||||
acpi_video_unregister();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ static inline acpi_status acpi_set_waking_vector(u32 wakeup_address)
|
||||
extern int acpi_s2idle_begin(void);
|
||||
extern int acpi_s2idle_prepare(void);
|
||||
extern int acpi_s2idle_prepare_late(void);
|
||||
extern void acpi_s2idle_check(void);
|
||||
extern bool acpi_s2idle_wake(void);
|
||||
extern void acpi_s2idle_restore_early(void);
|
||||
extern void acpi_s2idle_restore(void);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -584,6 +584,19 @@ int acpi_s2idle_prepare_late(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void acpi_s2idle_check(void)
|
||||
{
|
||||
struct acpi_s2idle_dev_ops *handler;
|
||||
|
||||
if (!lps0_device_handle || sleep_no_lps0)
|
||||
return;
|
||||
|
||||
list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
|
||||
if (handler->check)
|
||||
handler->check();
|
||||
}
|
||||
}
|
||||
|
||||
void acpi_s2idle_restore_early(void)
|
||||
{
|
||||
struct acpi_s2idle_dev_ops *handler;
|
||||
@@ -625,6 +638,7 @@ static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
|
||||
.begin = acpi_s2idle_begin,
|
||||
.prepare = acpi_s2idle_prepare,
|
||||
.prepare_late = acpi_s2idle_prepare_late,
|
||||
.check = acpi_s2idle_check,
|
||||
.wake = acpi_s2idle_wake,
|
||||
.restore_early = acpi_s2idle_restore_early,
|
||||
.restore = acpi_s2idle_restore,
|
||||
|
||||
@@ -874,10 +874,11 @@ config GPIO_104_IDI_48
|
||||
module parameter.
|
||||
|
||||
config GPIO_F7188X
|
||||
tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support"
|
||||
tristate "Fintek and Nuvoton Super-I/O GPIO support"
|
||||
help
|
||||
This option enables support for GPIOs found on Fintek Super-I/O
|
||||
chips F71869, F71869A, F71882FG, F71889F and F81866.
|
||||
As well as Nuvoton Super-I/O chip NCT6116D.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called f7188x-gpio.
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* GPIO driver for Fintek Super-I/O F71869, F71869A, F71882, F71889 and F81866
|
||||
* GPIO driver for Fintek and Nuvoton Super-I/O chips
|
||||
*
|
||||
* Copyright (C) 2010-2013 LaCie
|
||||
*
|
||||
* Author: Simon Guinot <simon.guinot@sequanux.org>
|
||||
*/
|
||||
|
||||
#define DRVNAME "gpio-f7188x"
|
||||
#define pr_fmt(fmt) DRVNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -14,30 +17,41 @@
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define DRVNAME "gpio-f7188x"
|
||||
|
||||
/*
|
||||
* Super-I/O registers
|
||||
*/
|
||||
#define SIO_LDSEL 0x07 /* Logical device select */
|
||||
#define SIO_DEVID 0x20 /* Device ID (2 bytes) */
|
||||
#define SIO_DEVREV 0x22 /* Device revision */
|
||||
#define SIO_MANID 0x23 /* Fintek ID (2 bytes) */
|
||||
|
||||
#define SIO_LD_GPIO 0x06 /* GPIO logical device */
|
||||
#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
|
||||
#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
|
||||
|
||||
#define SIO_FINTEK_ID 0x1934 /* Manufacturer ID */
|
||||
/*
|
||||
* Fintek devices.
|
||||
*/
|
||||
#define SIO_FINTEK_DEVREV 0x22 /* Fintek Device revision */
|
||||
#define SIO_FINTEK_MANID 0x23 /* Fintek ID (2 bytes) */
|
||||
|
||||
#define SIO_FINTEK_ID 0x1934 /* Manufacturer ID */
|
||||
|
||||
#define SIO_F71869_ID 0x0814 /* F71869 chipset ID */
|
||||
#define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */
|
||||
#define SIO_F71882_ID 0x0541 /* F71882 chipset ID */
|
||||
#define SIO_F71889_ID 0x0909 /* F71889 chipset ID */
|
||||
#define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */
|
||||
#define SIO_F81866_ID 0x1010 /* F81866 chipset ID */
|
||||
#define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same for f81966 */
|
||||
#define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same for F81966 */
|
||||
#define SIO_F81865_ID 0x0704 /* F81865 chipset ID */
|
||||
|
||||
#define SIO_LD_GPIO_FINTEK 0x06 /* GPIO logical device */
|
||||
|
||||
/*
|
||||
* Nuvoton devices.
|
||||
*/
|
||||
#define SIO_NCT6116D_ID 0xD283 /* NCT6116D chipset ID */
|
||||
|
||||
#define SIO_LD_GPIO_NUVOTON 0x07 /* GPIO logical device */
|
||||
|
||||
|
||||
enum chips {
|
||||
f71869,
|
||||
@@ -48,6 +62,7 @@ enum chips {
|
||||
f81866,
|
||||
f81804,
|
||||
f81865,
|
||||
nct6116d,
|
||||
};
|
||||
|
||||
static const char * const f7188x_names[] = {
|
||||
@@ -59,10 +74,12 @@ static const char * const f7188x_names[] = {
|
||||
"f81866",
|
||||
"f81804",
|
||||
"f81865",
|
||||
"nct6116d",
|
||||
};
|
||||
|
||||
struct f7188x_sio {
|
||||
int addr;
|
||||
int device;
|
||||
enum chips type;
|
||||
};
|
||||
|
||||
@@ -110,7 +127,7 @@ static inline int superio_enter(int base)
|
||||
{
|
||||
/* Don't step on other drivers' I/O space by accident. */
|
||||
if (!request_muxed_region(base, 2, DRVNAME)) {
|
||||
pr_err(DRVNAME "I/O address 0x%04x already in use\n", base);
|
||||
pr_err("I/O address 0x%04x already in use\n", base);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@@ -146,10 +163,10 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
|
||||
static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
unsigned long config);
|
||||
|
||||
#define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \
|
||||
#define F7188X_GPIO_BANK(_base, _ngpio, _regbase, _label) \
|
||||
{ \
|
||||
.chip = { \
|
||||
.label = DRVNAME, \
|
||||
.label = _label, \
|
||||
.owner = THIS_MODULE, \
|
||||
.get_direction = f7188x_gpio_get_direction, \
|
||||
.direction_input = f7188x_gpio_direction_in, \
|
||||
@@ -164,94 +181,108 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
.regbase = _regbase, \
|
||||
}
|
||||
|
||||
#define gpio_dir(base) (base + 0)
|
||||
#define gpio_data_out(base) (base + 1)
|
||||
#define gpio_data_in(base) (base + 2)
|
||||
#define f7188x_gpio_dir(base) ((base) + 0)
|
||||
#define f7188x_gpio_data_out(base) ((base) + 1)
|
||||
#define f7188x_gpio_data_in(base) ((base) + 2)
|
||||
/* Output mode register (0:open drain 1:push-pull). */
|
||||
#define gpio_out_mode(base) (base + 3)
|
||||
#define f7188x_gpio_out_mode(base) ((base) + 3)
|
||||
|
||||
#define f7188x_gpio_dir_invert(type) ((type) == nct6116d)
|
||||
#define f7188x_gpio_data_single(type) ((type) == nct6116d)
|
||||
|
||||
static struct f7188x_gpio_bank f71869_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 6, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0),
|
||||
F7188X_GPIO_BANK(60, 6, 0x90),
|
||||
F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 6, 0x90, DRVNAME "-6"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71869a_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 6, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80),
|
||||
F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71882_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(30, 4, 0xC0),
|
||||
F7188X_GPIO_BANK(40, 4, 0xB0),
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 4, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 4, 0xB0, DRVNAME "-4"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71889a_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 7, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 7, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80),
|
||||
F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f71889_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 7, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 7, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80),
|
||||
F7188X_GPIO_BANK(0, 7, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 7, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 5, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f81866_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80),
|
||||
F7188X_GPIO_BANK(80, 8, 0x88),
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-7"),
|
||||
F7188X_GPIO_BANK(80, 8, 0x88, DRVNAME "-8"),
|
||||
};
|
||||
|
||||
|
||||
static struct f7188x_gpio_bank f81804_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80),
|
||||
F7188X_GPIO_BANK(90, 8, 0x98),
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(60, 8, 0x90, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(70, 8, 0x80, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(90, 8, 0x98, DRVNAME "-6"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank f81865_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0),
|
||||
F7188X_GPIO_BANK(60, 5, 0x90),
|
||||
F7188X_GPIO_BANK(0, 8, 0xF0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE0, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xD0, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xC0, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xB0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xA0, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"),
|
||||
};
|
||||
|
||||
static struct f7188x_gpio_bank nct6116d_gpio_bank[] = {
|
||||
F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"),
|
||||
F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"),
|
||||
F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"),
|
||||
F7188X_GPIO_BANK(30, 8, 0xEC, DRVNAME "-3"),
|
||||
F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"),
|
||||
F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"),
|
||||
F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"),
|
||||
F7188X_GPIO_BANK(70, 1, 0xFC, DRVNAME "-7"),
|
||||
};
|
||||
|
||||
static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
@@ -264,13 +295,16 @@ static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
err = superio_enter(sio->addr);
|
||||
if (err)
|
||||
return err;
|
||||
superio_select(sio->addr, SIO_LD_GPIO);
|
||||
superio_select(sio->addr, sio->device);
|
||||
|
||||
dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
|
||||
dir = superio_inb(sio->addr, f7188x_gpio_dir(bank->regbase));
|
||||
|
||||
superio_exit(sio->addr);
|
||||
|
||||
if (dir & 1 << offset)
|
||||
if (f7188x_gpio_dir_invert(sio->type))
|
||||
dir = ~dir;
|
||||
|
||||
if (dir & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
@@ -286,11 +320,15 @@ static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
|
||||
err = superio_enter(sio->addr);
|
||||
if (err)
|
||||
return err;
|
||||
superio_select(sio->addr, SIO_LD_GPIO);
|
||||
superio_select(sio->addr, sio->device);
|
||||
|
||||
dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
|
||||
dir &= ~BIT(offset);
|
||||
superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
|
||||
dir = superio_inb(sio->addr, f7188x_gpio_dir(bank->regbase));
|
||||
|
||||
if (f7188x_gpio_dir_invert(sio->type))
|
||||
dir |= BIT(offset);
|
||||
else
|
||||
dir &= ~BIT(offset);
|
||||
superio_outb(sio->addr, f7188x_gpio_dir(bank->regbase), dir);
|
||||
|
||||
superio_exit(sio->addr);
|
||||
|
||||
@@ -307,14 +345,14 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
err = superio_enter(sio->addr);
|
||||
if (err)
|
||||
return err;
|
||||
superio_select(sio->addr, SIO_LD_GPIO);
|
||||
superio_select(sio->addr, sio->device);
|
||||
|
||||
dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
|
||||
dir = superio_inb(sio->addr, f7188x_gpio_dir(bank->regbase));
|
||||
dir = !!(dir & BIT(offset));
|
||||
if (dir)
|
||||
data = superio_inb(sio->addr, gpio_data_out(bank->regbase));
|
||||
if (f7188x_gpio_data_single(sio->type) || dir)
|
||||
data = superio_inb(sio->addr, f7188x_gpio_data_out(bank->regbase));
|
||||
else
|
||||
data = superio_inb(sio->addr, gpio_data_in(bank->regbase));
|
||||
data = superio_inb(sio->addr, f7188x_gpio_data_in(bank->regbase));
|
||||
|
||||
superio_exit(sio->addr);
|
||||
|
||||
@@ -332,18 +370,21 @@ static int f7188x_gpio_direction_out(struct gpio_chip *chip,
|
||||
err = superio_enter(sio->addr);
|
||||
if (err)
|
||||
return err;
|
||||
superio_select(sio->addr, SIO_LD_GPIO);
|
||||
superio_select(sio->addr, sio->device);
|
||||
|
||||
data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
|
||||
data_out = superio_inb(sio->addr, f7188x_gpio_data_out(bank->regbase));
|
||||
if (value)
|
||||
data_out |= BIT(offset);
|
||||
else
|
||||
data_out &= ~BIT(offset);
|
||||
superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
|
||||
superio_outb(sio->addr, f7188x_gpio_data_out(bank->regbase), data_out);
|
||||
|
||||
dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
|
||||
dir |= BIT(offset);
|
||||
superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
|
||||
dir = superio_inb(sio->addr, f7188x_gpio_dir(bank->regbase));
|
||||
if (f7188x_gpio_dir_invert(sio->type))
|
||||
dir &= ~BIT(offset);
|
||||
else
|
||||
dir |= BIT(offset);
|
||||
superio_outb(sio->addr, f7188x_gpio_dir(bank->regbase), dir);
|
||||
|
||||
superio_exit(sio->addr);
|
||||
|
||||
@@ -360,14 +401,14 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
err = superio_enter(sio->addr);
|
||||
if (err)
|
||||
return;
|
||||
superio_select(sio->addr, SIO_LD_GPIO);
|
||||
superio_select(sio->addr, sio->device);
|
||||
|
||||
data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
|
||||
data_out = superio_inb(sio->addr, f7188x_gpio_data_out(bank->regbase));
|
||||
if (value)
|
||||
data_out |= BIT(offset);
|
||||
else
|
||||
data_out &= ~BIT(offset);
|
||||
superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
|
||||
superio_outb(sio->addr, f7188x_gpio_data_out(bank->regbase), data_out);
|
||||
|
||||
superio_exit(sio->addr);
|
||||
}
|
||||
@@ -388,14 +429,14 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
err = superio_enter(sio->addr);
|
||||
if (err)
|
||||
return err;
|
||||
superio_select(sio->addr, SIO_LD_GPIO);
|
||||
superio_select(sio->addr, sio->device);
|
||||
|
||||
data = superio_inb(sio->addr, gpio_out_mode(bank->regbase));
|
||||
data = superio_inb(sio->addr, f7188x_gpio_out_mode(bank->regbase));
|
||||
if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
|
||||
data &= ~BIT(offset);
|
||||
else
|
||||
data |= BIT(offset);
|
||||
superio_outb(sio->addr, gpio_out_mode(bank->regbase), data);
|
||||
superio_outb(sio->addr, f7188x_gpio_out_mode(bank->regbase), data);
|
||||
|
||||
superio_exit(sio->addr);
|
||||
return 0;
|
||||
@@ -449,6 +490,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
|
||||
data->nr_bank = ARRAY_SIZE(f81865_gpio_bank);
|
||||
data->bank = f81865_gpio_bank;
|
||||
break;
|
||||
case nct6116d:
|
||||
data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank);
|
||||
data->bank = nct6116d_gpio_bank;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -479,18 +524,15 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
|
||||
{
|
||||
int err;
|
||||
u16 devid;
|
||||
u16 manid;
|
||||
|
||||
err = superio_enter(addr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = -ENODEV;
|
||||
devid = superio_inw(addr, SIO_MANID);
|
||||
if (devid != SIO_FINTEK_ID) {
|
||||
pr_debug(DRVNAME ": Not a Fintek device at 0x%08x\n", addr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
sio->device = SIO_LD_GPIO_FINTEK;
|
||||
devid = superio_inw(addr, SIO_DEVID);
|
||||
switch (devid) {
|
||||
case SIO_F71869_ID:
|
||||
@@ -517,17 +559,30 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
|
||||
case SIO_F81865_ID:
|
||||
sio->type = f81865;
|
||||
break;
|
||||
case SIO_NCT6116D_ID:
|
||||
sio->device = SIO_LD_GPIO_NUVOTON;
|
||||
sio->type = nct6116d;
|
||||
break;
|
||||
default:
|
||||
pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid);
|
||||
pr_info("Unsupported Fintek device 0x%04x\n", devid);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* double check manufacturer where possible */
|
||||
if (sio->type != nct6116d) {
|
||||
manid = superio_inw(addr, SIO_FINTEK_MANID);
|
||||
if (manid != SIO_FINTEK_ID) {
|
||||
pr_debug("Not a Fintek device at 0x%08x\n", addr);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
sio->addr = addr;
|
||||
err = 0;
|
||||
|
||||
pr_info(DRVNAME ": Found %s at %#x, revision %d\n",
|
||||
f7188x_names[sio->type],
|
||||
(unsigned int) addr,
|
||||
(int) superio_inb(addr, SIO_DEVREV));
|
||||
pr_info("Found %s at %#x\n", f7188x_names[sio->type], (unsigned int)addr);
|
||||
if (sio->type != nct6116d)
|
||||
pr_info(" revision %d\n", superio_inb(addr, SIO_FINTEK_DEVREV));
|
||||
|
||||
err:
|
||||
superio_exit(addr);
|
||||
@@ -548,13 +603,13 @@ f7188x_gpio_device_add(const struct f7188x_sio *sio)
|
||||
err = platform_device_add_data(f7188x_gpio_pdev,
|
||||
sio, sizeof(*sio));
|
||||
if (err) {
|
||||
pr_err(DRVNAME "Platform data allocation failed\n");
|
||||
pr_err("Platform data allocation failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = platform_device_add(f7188x_gpio_pdev);
|
||||
if (err) {
|
||||
pr_err(DRVNAME "Device addition failed\n");
|
||||
pr_err("Device addition failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,6 +248,13 @@ config DRM_RADEON
|
||||
select HWMON
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select INTERVAL_TREE
|
||||
# radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
|
||||
# ACPI_VIDEO's dependencies must also be selected.
|
||||
select INPUT if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
# On x86 ACPI_VIDEO also needs ACPI_WMI
|
||||
select X86_PLATFORM_DEVICES if ACPI && X86
|
||||
select ACPI_WMI if ACPI && X86
|
||||
help
|
||||
Choose this option if you have an ATI Radeon graphics card. There
|
||||
are both PCI and AGP versions. You don't need to choose this to
|
||||
@@ -273,6 +280,13 @@ config DRM_AMDGPU
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select INTERVAL_TREE
|
||||
select DRM_BUDDY
|
||||
# amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work
|
||||
# ACPI_VIDEO's dependencies must also be selected.
|
||||
select INPUT if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
# On x86 ACPI_VIDEO also needs ACPI_WMI
|
||||
select X86_PLATFORM_DEVICES if ACPI && X86
|
||||
select ACPI_WMI if ACPI && X86
|
||||
help
|
||||
Choose this option if you have a recent AMD Radeon graphics card.
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include "amdgpu.h"
|
||||
@@ -182,7 +184,12 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode
|
||||
return;
|
||||
|
||||
if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU))
|
||||
return;
|
||||
goto register_acpi_backlight;
|
||||
|
||||
if (!acpi_video_backlight_use_native()) {
|
||||
drm_info(dev, "Skipping amdgpu atom DIG backlight registration\n");
|
||||
goto register_acpi_backlight;
|
||||
}
|
||||
|
||||
pdata = kmalloc(sizeof(struct amdgpu_backlight_privdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
@@ -218,6 +225,11 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode
|
||||
error:
|
||||
kfree(pdata);
|
||||
return;
|
||||
|
||||
register_acpi_backlight:
|
||||
/* Try registering an ACPI video backlight device instead. */
|
||||
acpi_video_register_backlight();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -89,6 +89,8 @@
|
||||
#include <drm/drm_audio_component.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
|
||||
|
||||
#include "dcn/dcn_1_0_offset.h"
|
||||
@@ -4058,6 +4060,13 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
|
||||
amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps);
|
||||
dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL;
|
||||
|
||||
if (!acpi_video_backlight_use_native()) {
|
||||
drm_info(adev_to_drm(dm->adev), "Skipping amdgpu DM backlight registration\n");
|
||||
/* Try registering an ACPI video backlight device instead. */
|
||||
acpi_video_register_backlight();
|
||||
return;
|
||||
}
|
||||
|
||||
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.type = BACKLIGHT_RAW;
|
||||
|
||||
@@ -7,6 +7,8 @@ config DRM_GMA500
|
||||
select ACPI_VIDEO if ACPI
|
||||
select BACKLIGHT_CLASS_DEVICE if ACPI
|
||||
select INPUT if ACPI
|
||||
select X86_PLATFORM_DEVICES if ACPI
|
||||
select ACPI_WMI if ACPI
|
||||
help
|
||||
Say yes for an experimental 2D KMS framebuffer driver for the
|
||||
Intel GMA500 (Poulsbo), Intel GMA600 (Moorestown/Oak Trail) and
|
||||
|
||||
@@ -23,6 +23,8 @@ config DRM_I915
|
||||
# but for select to work, need to select ACPI_VIDEO's dependencies, ick
|
||||
select BACKLIGHT_CLASS_DEVICE if ACPI
|
||||
select INPUT if ACPI
|
||||
select X86_PLATFORM_DEVICES if ACPI
|
||||
select ACPI_WMI if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
select ACPI_BUTTON if ACPI
|
||||
select SYNC_FILE
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_acpi.h"
|
||||
@@ -331,3 +332,29 @@ void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915)
|
||||
*/
|
||||
fwnode_handle_put(fwnode);
|
||||
}
|
||||
|
||||
void intel_acpi_video_register(struct drm_i915_private *i915)
|
||||
{
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct drm_connector *connector;
|
||||
|
||||
acpi_video_register();
|
||||
|
||||
/*
|
||||
* If i915 is driving an internal panel without registering its native
|
||||
* backlight handler try to register the acpi_video backlight.
|
||||
* For panels not driven by i915 another GPU driver may still register
|
||||
* a native backlight later and acpi_video_register_backlight() should
|
||||
* only be called after any native backlights have been registered.
|
||||
*/
|
||||
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
struct intel_panel *panel = &to_intel_connector(connector)->panel;
|
||||
|
||||
if (panel->backlight.funcs && !panel->backlight.device) {
|
||||
acpi_video_register_backlight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ void intel_unregister_dsm_handler(void);
|
||||
void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915);
|
||||
void intel_acpi_device_id_update(struct drm_i915_private *i915);
|
||||
void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915);
|
||||
void intel_acpi_video_register(struct drm_i915_private *i915);
|
||||
#else
|
||||
static inline void intel_register_dsm_handler(void) { return; }
|
||||
static inline void intel_unregister_dsm_handler(void) { return; }
|
||||
@@ -23,6 +24,8 @@ static inline
|
||||
void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; }
|
||||
static inline
|
||||
void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) { return; }
|
||||
static inline
|
||||
void intel_acpi_video_register(struct drm_i915_private *i915) { return; }
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /* __INTEL_ACPI_H__ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user