* Re: [RFC PATCH v3] platform/x86: panasonic-laptop: Add platform_profile support
2026-10-07 19:04 [RFC PATCH v3] platform/x86: panasonic-laptop: Add platform_profile support Alex Yeo
@ 2026-10-12 3:42 ` Wu Zhipeng
2026-10-15 9:55 ` Alex Yeo
2026-10-16 11:12 ` Ilpo Järvinen
1 sibling, 1 reply; 5+ messages in thread
From: Wu Zhipeng @ 2026-10-12 3:42 UTC (permalink / raw)
To: Alex Yeo
Cc: platform-driver-x86, linux-acpi, Ilpo Jarvinen, Hans de Goede,
Hans de Goede, Kenneth Chan
[-- Attachment #1: Type: text/plain, Size: 13038 bytes --]
Hi Alex,
Thanks for the RFC and for carrying the series through v3. I tested this
on a Panasonic CF-SV1-2 (product name "CFSV1-2" per dmidecode,
i5-1145G7, BIOS V2.00L23), which exposes the same SEFM/SEPL/CEFM/EPLE
method quartet and the same 4-state fan/TDP matrix your driver relies
on. The _SB.IETM._OSC region from this unit's dump is in the excerpt
below if it helps place it in your A/B grouping.
Summary of my findings:
1. CF-SV1-2 is not in v3's tested list or DMI table. Mirroring the v3
CF-SR4 table, the mapping here is: active+locked -> COOL,
passive+locked -> QUIET, active+unlocked -> PERFORMANCE, which
leaves passive+unlocked to fall out as CUSTOM exactly as get()
reports unmapped states. The startup default on this unit is
CEFM=0 / EPLE=1, i.e. active+locked (COOL), the same shape as your
per-model "Startup default" notes. One mapping note: COOL is
currently SR4-only, but on the SV1 the active fan is likewise the
aggressive setting (4 C cooler at the same package power, below),
so SV1 would be a second COOL model. A quirk patch rebased onto
your v3 is attached (a starting point, not for direct merge).
2. Measured on this unit, the fan toggle is the dominant lever: it
moves the peak package temperature by +4 C on AC and +9..10 C on
battery, with package power essentially flat (fan effect <= 0.05 W
on AC and <= 0.25 W on battery). The TDP toggle moves much less:
<= 0.05 W and +2 C on AC, <= 0.41 W and +5..6 C on battery. Even
with EPP pinned to performance the package stayed at <= 2.6 GHz /
~10.5 W, and I could not establish from the OS side what still caps
it; I flag this because it affects what "unlocked" should mean on
this generation.
3. A few model-specific AML details I noticed (SSDT excerpts are appended
below):
· REFM writes a curve byte to EC register 0x79 and the values are
model-specific: this SV1 uses 0x00 (CEFM=0) / 0x05 (CEFM=1) /
0x02 under S0i3, while the SR4 REFM quoted in your fan-speed RFC
v8 (its ssdt10.dsl) swaps the latter two. Only the SEFM boolean
is portable, so the curve bytes shouldn't be documented as
universal.
· REPL has four outcomes, not a binary cap: EPLE=1 selects an IETM
table PL (P140/P143 here; the battery locked runs land on
P140 = 10 W) and EPLE=0 gives the 0xFF no-limit branch, so the
effective wattage comes from the IETM tables rather than a fixed
number. v3's EPLE read matches what the EC does.
· _FST's second field is the fan setpoint (PEN1), not RPM.
· While TFN1._FSL holds a nonzero override, the EC ignores the
curve register, masking platform_profile set(). Your decision not
to touch _FSL looks correct.
· Consistent with the WAK -> REPL/REFM/... chain, the profile
setting survives suspend/resume (verified with rtcwake).
Data -- AC, userspace fan governance parked so the firmware owns the
fan; per state: write SEFM/SEPL, 30 s settle, then sysbench cpu
--threads=8 --time=60 with 1 s RAPL package sampling. PkgWatt = mean
package power over the 60 s window (RAPL energy delta); temp = highest
package temperature in that window; medians over 3 interleaved runs,
min-max in parentheses:
Configuration PkgWatt sustained sysbench pkg max
high(active) + locked 6.28 W (6.21-6.33) 5510 e/s 41.0 C (41-42)
quiet(passive) + locked 6.23 W (6.21-6.34) 5425 e/s 45.0 C (45-47)
quiet(passive) + unlocked 6.22 W (6.19-6.26) 5412 e/s 47.0 C (47-48)
high(active) + unlocked 6.23 W (6.22-6.25) 5481 e/s 43.0 C (42-44)
fan toggle (quiet - high) : package -0.05 W, pkg max +4.0 C @locked
package -0.02 W, pkg max +4.0 C @unlocked
TDP toggle (unlocked - locked): package -0.05 W, pkg max +2.0 C @high fan
package -0.02 W, pkg max +2.0 C @quiet fan
Battery -- same method, but EPP pinned to performance so the CPU asks
for more than the P140 table value; S0IX=0 / PWRS=0 throughout, i.e.
the P152/P154 branch never fires in working states (n=1, trend only):
Configuration PkgWatt sustained pkg max
high(active) + locked 9.98 W 48.0 C
quiet(passive) + locked 10.01 W 57.0 C
quiet(passive) + unlocked 10.42 W 63.0 C
high(active) + unlocked 10.20 W 53.0 C
The locked states land on the P140 value (~10.0 W) and unlocking adds
only 0.2-0.4 W here, so the TDP toggle stays a minor lever on battery
as well.
Reproducibility: kernel 7.0.0-38-generic, iasl 20251212; a fresh
acpidump -b on the unit gives ssdt2.dat sha256
f0d92acff1f43c29c7921ebeb6951375f21d5fc554e7070426c6b9e8f62f5f61, and
decompiling it gives ssdt2.dsl sha256 913edf1cf5571f2b... (the regions
quoted above are appended below). Per-run samples and the raw dump stay
on my side and are available on request.
Attached as plain text: cf-sv1-platform_profile-quirk.patch
(git-format-patch against your v3) and the two summary tables above as
summary-ac.csv / summary-battery.csv. The SSDT excerpt is appended
below after the --- delimiter, and the full run logs are available on
request. Happy to build-test it here and send a Tested-by.
This message was drafted with the assistance of an AI coding agent;
all measurements and AML reading were reviewed by me against the raw
data.
Reported-by: Wu Zhipeng <zepwu@foxmail.com>
---
# Excerpt from ssdt2.dsl -- decompiled with iasl 20251212 from ssdt2.dat
# (sha256 f0d92acff1f43c29c7921ebeb6951375f21d5fc554e7070426c6b9e8f62f5f61,
# acpidump -b on the CF-SV1-2 under kernel 7.0.0-38-generic; the
# decompiled file's sha256 starts 913edf1cf5571f2b).
# Line numbers refer to the decompiled file. The mail quotes the
# relevant parts inline (C1/C2); this file is the surrounding context.
# ---- \_SB.IETM._OSC : sets SEFM/SEPL from the OS capabilities ----
355 Method (_OSC, 4, Serialized) // _OSC: Operating System Capabilities
356 {
357 CreateDWordField (Arg3, Zero, STS1)
358 CreateDWordField (Arg3, 0x04, CAP1)
359 If ((Arg1 != One))
360 {
361 STS1 &= 0xFFFFFF00
362 STS1 |= 0x0A
363 Return (Arg3)
364 }
365
366 If ((Arg2 != 0x02))
367 {
368 STS1 &= 0xFFFFFF00
369 STS1 |= 0x02
370 Return (Arg3)
371 }
372
373 If (CondRefOf (\_SB.APSV))
374 {
375 If ((PSEM == Zero))
376 {
377 PSEM = One
378 PTRP = \_SB.APSV /* External reference */
379 }
380 }
381
382 If (CondRefOf (\_SB.AAC0))
383 {
384 If ((ASEM == Zero))
385 {
386 ASEM = One
387 ATRP = \_SB.AAC0 /* External reference */
388 }
389 }
390
391 If (CondRefOf (\_SB.ACRT))
392 {
393 If ((YSEM == Zero))
394 {
395 YSEM = One
396 YTRP = \_SB.ACRT /* External reference */
397 }
398 }
399
400 If ((Arg0 == ToUUID ("b23ba85d-c8b7-3542-88de-8de2ffcfd698") /* Unknown UUID */))
401 {
402 If (~(STS1 & One))
403 {
404 If ((CAP1 & One))
405 {
406 If ((CAP1 & 0x02))
407 {
408 \_SB.AAC0 = 0x6E
409 \_SB.PC00.LPCB.EC0.SEFM (One)
410 }
411 Else
412 {
413 \_SB.AAC0 = ATRP /* \_SB_.IETM.ATRP */
414 \_SB.PC00.LPCB.EC0.SEFM (Zero)
415 }
416
417 If ((CAP1 & 0x04))
418 {
419 \_SB.APSV = 0x6E
420 \_SB.PC00.LPCB.EC0.SEPL (Zero)
421 \_SB.PC00.TCPU.TDPL ()
422 }
423 Else
424 {
425 \_SB.APSV = PTRP /* \_SB_.IETM.PTRP */
426 \_SB.PC00.LPCB.EC0.SEPL (One)
427 }
428
429 If ((CAP1 & 0x08))
430 {
431 \_SB.ACRT = 0xD2
432 \_TZ.ETMD = Zero
433 }
434 Else
435 {
436 \_SB.ACRT = YTRP /* \_SB_.IETM.YTRP */
437 \_TZ.ETMD = One
438 }
439 }
440 Else
441 {
442 \_SB.ACRT = YTRP /* \_SB_.IETM.YTRP */
443 \_SB.APSV = PTRP /* \_SB_.IETM.PTRP */
444 \_SB.AAC0 = ATRP /* \_SB_.IETM.ATRP */
445 \_TZ.ETMD = One
446 }
447
448 If (CondRefOf (\_TZ.TZ00))
449 {
450 Notify (\_TZ.TZ00, 0x81) // Information Change
# ---- SEFM / REFM : CEFM -> fan curve byte (C1) ----
3640 Name (CEFM, Zero)
3641 Method (SEFM, 1, Serialized)
3642 {
3643 CEFM = Arg0
3644 REFM ()
3645 }
3646
3647 Method (REFM, 0, Serialized)
3648 {
3649 If ((\S0IX == 0x03))
3650 {
3651 \_SB.PC00.LPCB.EC0.EC88 (0xB5, 0x79, 0x02, Zero)
3652 }
3653 ElseIf ((CEFM == Zero))
3654 {
3655 \_SB.PC00.LPCB.EC0.EC88 (0xB5, 0x79, Zero, Zero)
3656 }
3657 Else
3658 {
3659 \_SB.PC00.LPCB.EC0.EC88 (0xB5, 0x79, 0x05, Zero)
3660 }
3661 }
# ---- SEPL / REPL : EPLE/S0IX/PWRS -> power limit table (C2) ----
3663 Name (EPLE, One)
3664 Method (SEPL, 1, Serialized)
3665 {
3666 EPLE = Arg0
3667 REPL ()
3668 }
3669
3670 Method (REPL, 0, Serialized)
3671 {
3672 Name (EPL1, 0xFF)
3673 Name (EPL2, 0xFF)
3674 Name (EPLT, Zero)
3675 If (((\S0IX == One) && (\PWRS == Zero)))
3676 {
3677 EPL1 = \_SB.IETM.P152
3678 EPL2 = \_SB.IETM.P154
3679 EPLT = \_SB.PC00.TCPU.CTN2 (\_SB.IETM.P153)
3680 }
3681 ElseIf ((\S0IX == 0x03))
3682 {
3683 EPL1 = \_SB.IETM.P164
3684 EPL2 = \_SB.IETM.P166
3685 EPLT = \_SB.PC00.TCPU.CTN2 (\_SB.IETM.P165)
3686 }
3687 ElseIf ((EPLE == One))
3688 {
3689 EPL1 = \_SB.IETM.P140
3690 EPL2 = \_SB.IETM.P143
3691 EPLT = \_SB.PC00.TCPU.CTN2 (\_SB.IETM.P142)
3692 If ((\_SB.PC00.LPCB.EC0.EC34 () > \_SB.IETM.CTOK (\_SB.IETM.P145)))
3693 {
3694 EPL1 = \_SB.IETM.P141
3695 }
3696 }
3697 Else
3698 {
3699 }
3700
3701 \_SB.PC00.LPCB.EC0.EC88 (0xB5, 0xCA, EPL1, EPLT)
3702 \_SB.PC00.LPCB.EC0.EC88 (0xB5, 0xCB, EPL2, Zero)
3703 }
# ---- \_SB.IETM.WAK : re-applies REPL/REFM/REFD/SCGR after resume ----
3717 Method (WAK, 1, Serialized)
3718 {
3719 \_SB.PC00.LPCB.EC0.REPL ()
3720 \_SB.PC00.LPCB.EC0.REFM ()
3721 \_SB.PC00.LPCB.EC0.REFD ()
3722 \_SB.PC00.LPCB.EC0.SCGR (Zero)
3723 }
[-- Attachment #2: cf-sv1-platform_profile-quirk.patch --]
[-- Type: text/plain, Size: 4037 bytes --]
From c7636af72db7a4c649914ff3fe9bb67b184a16d9 Mon Sep 17 00:00:00 2001
From: Wu Zhipeng <zepwu@foxmail.com>
Date: Mon, 12 Oct 2026 11:35:21 +0800
Subject: [PATCH] platform/x86: panasonic-laptop: add platform_profile quirk
for CF-SV1-2
Add a platform_profile quirk for the Panasonic CF-SV1-2 (Let's Note,
Tiger Lake), verified on hardware with BIOS V2.00L23. The firmware
exposes the same fan and TDP policy controls as CF-SR4 (CEFM/EPLE state
variables, _SB.IETM P14x/P15x power tables, and the WAK ->
REPL/REFM/REFD/SCGR re-apply chain), so the model maps onto
COOL/QUIET/PERFORMANCE following the CF-SR4 table; the remaining
fan/TDP combination is reported as CUSTOM by get().
Measured on the unit, the fan policy toggle dominates: in the
power-saver regime the CPU temperature differs by 5.0 C between the
high-fan and quiet curves (7-8 C with a more aggressive EPP), while
the TDP toggle moves package power by <= 0.1 W in that regime and by
~0.5 W at most in the others.
Model-specific behaviour is captured in comments because it does not
generalise across models: the SEFM curve-byte values are swapped
against CF-SR4, EPLE/SEPL select an IETM table PL rather than a fixed
TDP cap, _FST[1] is a fan setpoint and not RPM, and a nonzero TFN1._FSL
override masks a profile change until it is released.
Signed-off-by: Wu Zhipeng <zepwu@foxmail.com>
---
Starting point against RFC v3, not for direct merge. Rebased onto the
v3 pcc_profile platform_driver; model notes updated to v3's method
names (CEFM/EPLE read, SEFM/SEPL write) and the CUSTOM handling
aligns with get() reporting unrecognised states as CUSTOM.
---
drivers/platform/x86/panasonic-laptop.c | 43 +++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index c4b13a3..aabc781 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -307,6 +307,41 @@ static struct pcc_profile_quirk quirk_cf_sr4 = {
},
};
+/*
+ * Model notes, CF-SV1-2 (verified on hardware, BIOS V2.00L23):
+ * - The fan request itself is a boolean (SEFM/CEFM), but the curve byte
+ * the EC maps it to is model specific (CF-SV1: 0x00 cool / 0x05 quiet /
+ * 0x02 in S0i3, i.e. the quiet and S0i3 bytes are swapped relative to
+ * CF-SR4). Only the boolean is portable; do not document the curve
+ * byte values as universal.
+ * - EPLE reports the TDP state and SEPL applies it; EPLE = 1 selects an
+ * IETM table PL and EPLE = 0 means no limit (EPL1 = EPL2 = 0xFF). The
+ * EC derives the actual value from the IETM P14x/P15x tables, so the
+ * resulting limit is not a single fixed number.
+ * - _FST[1] is the fan setpoint (PEN1), not RPM.
+ * - While TFN1._FSL holds a nonzero override the EC ignores the curve
+ * register, so a profile change is masked until the override is
+ * released; this driver deliberately does not touch _FSL.
+ * - At boot the EC comes up with CEFM = 0 and EPLE = 1 (those are the
+ * AML reset values), i.e. active + locked / COOL.
+ */
+static struct pcc_profile_quirk quirk_cf_sv1 = {
+ .platform_profiles = {
+ [PLATFORM_PROFILE_QUIET] = {
+ .fan_mode = PCC_FAN_MODE_PASSIVE,
+ .tdp_mode = PCC_TDP_MODE_LOCKED,
+ },
+ [PLATFORM_PROFILE_COOL] = {
+ .fan_mode = PCC_FAN_MODE_ACTIVE,
+ .tdp_mode = PCC_TDP_MODE_LOCKED,
+ },
+ [PLATFORM_PROFILE_PERFORMANCE] = {
+ .fan_mode = PCC_FAN_MODE_ACTIVE,
+ .tdp_mode = PCC_TDP_MODE_UNLOCKED,
+ },
+ },
+};
+
static struct pcc_profile_quirk quirk_cf_qv9 = {
.platform_profiles = {
[PLATFORM_PROFILE_BALANCED] = {
@@ -355,6 +390,14 @@ static const struct dmi_system_id pcc_profile_quirks[] = {
},
.driver_data = &quirk_cf_sr4,
},
+ {
+ .ident = "Panasonic Corporation CFSV1-2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Panasonic Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CFSV1-2"),
+ },
+ .driver_data = &quirk_cf_sv1,
+ },
{
.ident = "Panasonic Corporation CFQV9-1",
.matches = {
--
2.53.0
[-- Attachment #3: summary-ac.csv --]
[-- Type: text/plain, Size: 303 bytes --]
state,n,pkgW_mean_window,pkgW_min,pkgW_max,pkg_temp_max_C_median,notes
high(active)+locked,3,6.28,6.21,6.33,41.0,SEFM/SEPL=0_1
quiet(passive)+locked,3,6.23,6.21,6.34,45.0,SEFM/SEPL=1_1
quiet(passive)+unlocked,3,6.22,6.19,6.26,47.0,SEFM/SEPL=1_0
high(active)+unlocked,3,6.23,6.22,6.25,43.0,SEFM/SEPL=0_0
[-- Attachment #4: summary-battery.csv --]
[-- Type: text/plain, Size: 361 bytes --]
state,n,pkgW_mean_window,pkg_temp_max_C,notes
high(active)+locked,1,9.98,48.0,SEFM/SEPL=0_1; EPP=performance; S0IX=PWRS=0
quiet(passive)+locked,1,10.01,57.0,SEFM/SEPL=1_1; EPP=performance; S0IX=PWRS=0
quiet(passive)+unlocked,1,10.42,63.0,SEFM/SEPL=1_0; EPP=performance; S0IX=PWRS=0
high(active)+unlocked,1,10.20,53.0,SEFM/SEPL=0_0; EPP=performance; S0IX=PWRS=0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [RFC PATCH v3] platform/x86: panasonic-laptop: Add platform_profile support
2026-10-07 19:04 [RFC PATCH v3] platform/x86: panasonic-laptop: Add platform_profile support Alex Yeo
2026-10-12 3:42 ` Wu Zhipeng
@ 2026-10-16 11:12 ` Ilpo Järvinen
1 sibling, 0 replies; 5+ messages in thread
From: Ilpo Järvinen @ 2026-10-16 11:12 UTC (permalink / raw)
To: Alex Yeo; +Cc: platform-driver-x86, Hans de Goede, Kenneth Chan, LKML
On Thu, 8 Oct 2026, Alex Yeo wrote:
> Expose firmware thermal and power management policies via the
> platform_profile interface.
>
> Supported and tested models:
> - CF-RZ6 (2016)
> - CF-SV8 (2019)
> - CF-QV9 (2020)
> - CF-SR4 (2024)
>
> Firmware fan operating mode and the TDP limit switch are mapped onto
> the Linux platform_profile ABI.
>
> This implementation queries the firmware for every get().
> CUSTOM is returned when the current state is not recognized.
> The set() callback writes the values regardless of what the
> current fan mode and TDP limit is.
>
> - Introduce as separate platform_driver
> - Used DEFINE for driver and platform_profile device name
> - DMI quirks restrict support to tested models
> - When raising TDP, fan mode is switched first
> - When limiting TDP, TDP limit is applied first
> - ACPI handle for the EC device was used as the EC path varies
> slightly between models.
> - This device is optional: keep hotkey and everything already
> loaded if profile driver fails for any reason.
>
> Signed-off-by: Alex Yeo <alexyeo362@gmail.com>
> ---
> v3:
> - Removed sysfs.h import
> - Refactored platform profile probe function to use a different pattern
> (check warn_on, continue on double unset, then set)
>
> v2: https://lore.kernel.org/platform-driver-x86/20261006085021.853827-1-alexyeo362@gmail.com/
> - Refactored code to use its own platform_driver
> - Removed DEFINE_FREE and its corresponding __free as its addition
> in this module is inappropriate
> - Removed pr_fmt line as its addition to this patch is inappropriate
> - Added DMI check during __init to prevent attempt of platform profile
> device loading on unsupported hardware
> - Fixed use of enums as truth values by adding explicit comparisons
> - Added *profile_pdev to keep track of new platform_driver
> - Removed extra spaces in the quirk definitions
> - Added helper function for calling EC methods for simplicity
> - Use ARRAY_SIZE() for for loops and added include for array_size.h
> - Refactored pcc_profile to be a pointer in platform profile set
> function
> - Use WARN_ON() when a malformed quirk is detected in the platform
> profile probe function
> - Avoid use of status as variable name if not acpi_status
> - Added Kconfig line for ACPI_PLATFORM_PROFILE
> - Removed bool .use_platform_profiles from the quirks struct as it is
> no longer needed as a result of the platform_driver being separate.
> - Moved DMI quirk matching in probe function before devm_kzalloc of
> driver struct
>
> v1: https://lore.kernel.org/platform-driver-x86/20260805180544.1134916-1-alexyeo362@gmail.com/
>
> This RFC patch adds support for mapping firmware thermal and CPU power
> operating policy to platform_profile for Panasonic Let's Note laptops.
> This originally started as a hwmon and thermal patch, but further
> analysis had revealed that these are firmware power and thermal
> policies as opposed to fan control.
>
> Panasonic firmware exposes firmware operating policy through two
> methods:
> - Fan cooling policy (active/passive)
> - Processor TDP limit (capped/uncapped)
>
> At boot, firmware defaults to an active cooling policy with the
> CPU TDP capped. Vendor drivers / DPTF normally unlocks this on
> Windows.
>
> These 2 methods map to 4 possible distinct states. Only states that
> correspond to the platform_profile ABI are mapped and exposed as
> choices. Unmapped states will be returned as "custom" by the driver.
>
> I have tested the following models:
> - CF-RZ6 (2016)
> - CF-SV8 (2019)
> - CF-QV9 (2020)
> - CF-SR4 (2024)
>
> State to platform_profile mapping:
>
> Profile | Fan Mode | TDP
> +--------------------------------+-----------+------------+
> PLATFORM_PROFILE_COOL (SR4 only)| Active | Locked
> PLATFORM_PROFILE_BALANCED | Active | Locked
> PLATFORM_PROFILE_QUIET | Passive | Locked
> PLATFORM_PROFILE_PERFORMANCE | Active | Unlocked
> CUSTOM (unmapped on all) | Passive | Unlocked
>
> Across all of them, the fan and TDP modes are toggled by the same ACPI
> methods. However, there is a slight variation in its interpretation based
> on testing results.
>
> These methods are normally called by the DPTF/IPF _OSC handshake.
> Depending on the capability bits, the firmware will alter its thermal
> and power policy.
>
> \_SB.IETM Implementation A:
> - CF-RZ6 (2016)
> - CF-SV8 (2019)
>
> \_SB.IETM Implementation B:
> - CF-QV9 (2020)
> - CF-SR4 (2024)
>
> Models belonging to the same group share what appears to be identical
> AML code for the _OSC.
>
> This patch only exposes the ability to read and set these firmware
> toggles. The get() callback queries current firmware state and returns
> the mapped platform_profile. The set() callback sets the target state
> regardless of current state.
>
> Proposed mappings in this patch are defined in the quirks struct.
> Activation of platform_profile is gated by DMI checks.
>
> For every model except the SR4, only balanced and performance profiles
> are defined. This is because the aggressive fan paired with the locked
> TDP on the SR4 more appropriately correspond to the cool profile.
>
> Test results for the proposed mappings are below.
>
> Test results:
> ================
> (CPU PkgWatt: peak / sustained)
> (Sysbench CPU: all available threads)
>
> CF-RZ6: (i5-7Y57, Startup default: Balanced)
>
> Platform Profile | CPU PkgWatt | Sysbench CPU | Stress Temp (CPU)
> +-----------------+-----------------+----------------+-------------------+
> BALANCED | 10.0W / 9.0W | 19712 | 57C
> PERFORMANCE | 18.9W / 14.9W | 29132 | 72C
>
> CF-SV8: (i5-8365U, Startup default: Balanced)
>
> Platform Profile | CPU PkgWatt | Sysbench CPU | Stress Temp (CPU)
> +-----------------+------------------+----------------+-------------------+
> BALANCED | 9.9W / 9.9W | 44695 | 58C
> PERFORMANCE | 29.0W / 19.9W | 71747 | 81C
>
> CF-QV9: (i5-10310U, Startup default: Balanced)
>
> Platform Profile | CPU PkgWatt | Sysbench CPU | Stress Temp (CPU)
> +-----------------+------------------+----------------+-------------------+
> BALANCED | 10.0W / 9.9W | 46545 | 59C
> PERFORMANCE | 18.9W / 14.9W | 57416 | 70C
>
> CF-SR4: (i5-1345U, Startup default: Cool)
>
> Platform Profile | CPU PkgWatt | Sysbench CPU | Stress Temp (CPU)
> +-----------------+------------------+----------------+-------------------+
> COOL | 12.0W / 12.0W | 177139 | 66C
> QUIET | 12.0W / 12.0W | 176315 | 73C-75C
> PERFORMANCE | 29.6W / 21.3W | 247602 | 98C-100C
>
> CF-SR4 Notes:
> - QUIET: downclock/throttle at 75C, no increase in package_throttle_count
> - PERFORMANCE: stable boost clock, package_throttle_count increase
>
>
> Other notes:
> ===============
>
> Additional notes about thermald:
> During testing, I have observed that running thermald for the first time
> since boot will trigger an _OSC negotiation that will unlock CPU TDP for
> new models (IETM Implementation B). Once thermald is running, exits or
> runs again, these bits were not observed to change again during testing.
>
> Running thermald on older models (IETM Implementation A) does not touch
> the fan curve or TDP mode setting.
>
> Suspend: observed to not alter the values set prior to suspend
>
> drivers/platform/x86/Kconfig | 1 +
> drivers/platform/x86/panasonic-laptop.c | 399 +++++++++++++++++++++++-
> 2 files changed, 399 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index 957034f39e4e..571c09152310 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -820,6 +820,7 @@ config PANASONIC_LAPTOP
> depends on ACPI_VIDEO=n || ACPI_VIDEO
> depends on SERIO_I8042 || SERIO_I8042 = n
> select INPUT_SPARSEKMAP
> + select ACPI_PLATFORM_PROFILE
> help
> This driver adds support for access to backlight control and hotkeys
> on Panasonic Let's Note laptops.
> diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
> index 19d194ff37ca..c4b13a3554e3 100644
> --- a/drivers/platform/x86/panasonic-laptop.c
> +++ b/drivers/platform/x86/panasonic-laptop.c
> @@ -120,9 +120,13 @@
> */
>
> #include <linux/acpi.h>
> +#include <linux/array_size.h>
> #include <linux/backlight.h>
> #include <linux/bits.h>
> #include <linux/ctype.h>
> +#include <linux/dmi.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> #include <linux/i8042.h>
> #include <linux/init.h>
> #include <linux/input.h>
> @@ -130,6 +134,8 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/platform_device.h>
> +#include <linux/platform_profile.h>
> +#include <linux/printk.h>
> #include <linux/seq_file.h>
> #include <linux/serio.h>
> #include <linux/slab.h>
> @@ -158,10 +164,37 @@ MODULE_LICENSE("GPL");
> #define ECO_MODE_OFF 0x00
> #define ECO_MODE_ON 0x80
>
> +#define PCC_ACPI_FAN_ACTIVE_MODE 0x00
> +#define PCC_ACPI_FAN_PASSIVE_MODE 0x01
> +#define PCC_ACPI_TDP_LIMIT_ON 0x01
> +#define PCC_ACPI_TDP_LIMIT_OFF 0x00
> +
> #define ACPI_PCC_DRIVER_NAME "Panasonic Laptop Support"
> +#define PROFILE_PCC_DRIVER_NAME "panasonic-platform-profile"
>
> #define ACPI_PCC_INPUT_PHYS "panasonic/hkey0"
>
> +enum pcc_profile_fan_mode {
> + PCC_FAN_MODE_UNSET = 0,
> + PCC_FAN_MODE_ACTIVE,
> + PCC_FAN_MODE_PASSIVE,
> +};
> +
> +enum pcc_profile_tdp_mode {
> + PCC_TDP_MODE_UNSET = 0,
> + PCC_TDP_MODE_LOCKED,
> + PCC_TDP_MODE_UNLOCKED,
> +};
> +
> +struct pcc_platform_profile {
> + enum pcc_profile_fan_mode fan_mode;
> + enum pcc_profile_tdp_mode tdp_mode;
> +};
> +
> +struct pcc_profile_quirk {
> + struct pcc_platform_profile platform_profiles[PLATFORM_PROFILE_LAST];
> +};
> +
> /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent
> ECO_MODEs: 0x03 = off, 0x83 = on
> */
> @@ -251,6 +284,104 @@ struct pcc_acpi {
> u32 sinf[] __counted_by(num_sifr);
> };
>
> +struct pcc_profile {
> + acpi_handle ec_handle;
> + const struct pcc_profile_quirk *quirks;
> + struct device *platform_profile_dev;
> +};
> +
> +static struct pcc_profile_quirk quirk_cf_sr4 = {
> + .platform_profiles = {
> + [PLATFORM_PROFILE_QUIET] = {
> + .fan_mode = PCC_FAN_MODE_PASSIVE,
> + .tdp_mode = PCC_TDP_MODE_LOCKED,
> + },
> + [PLATFORM_PROFILE_COOL] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_LOCKED,
> + },
> + [PLATFORM_PROFILE_PERFORMANCE] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_UNLOCKED,
> + },
> + },
> +};
> +
> +static struct pcc_profile_quirk quirk_cf_qv9 = {
> + .platform_profiles = {
> + [PLATFORM_PROFILE_BALANCED] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_LOCKED,
> + },
> + [PLATFORM_PROFILE_PERFORMANCE] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_UNLOCKED,
> + },
> + },
> +};
> +
> +static struct pcc_profile_quirk quirk_cf_sv8 = {
> + .platform_profiles = {
> + [PLATFORM_PROFILE_BALANCED] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_LOCKED,
> + },
> + [PLATFORM_PROFILE_PERFORMANCE] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_UNLOCKED,
> + },
> + },
> +};
> +
> +static struct pcc_profile_quirk quirk_cf_rz6 = {
> + .platform_profiles = {
> + [PLATFORM_PROFILE_BALANCED] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_LOCKED,
> + },
> + [PLATFORM_PROFILE_PERFORMANCE] = {
> + .fan_mode = PCC_FAN_MODE_ACTIVE,
> + .tdp_mode = PCC_TDP_MODE_UNLOCKED,
> + },
> + },
> +};
Multiple of these look exact duplicates. In such cases, we try to reuse
the same struct even if we cannot then exactly match the name with the
model.
> +static const struct dmi_system_id pcc_profile_quirks[] = {
> + {
> + .ident = "Panasonic Connect Co., Ltd. CFSR4-1",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Panasonic Connect Co., Ltd."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "CFSR4-1"),
> + },
> + .driver_data = &quirk_cf_sr4,
> + },
> + {
> + .ident = "Panasonic Corporation CFQV9-1",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Panasonic Corporation"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "CFQV9-1"),
> + },
> + .driver_data = &quirk_cf_qv9,
> + },
> + {
> + .ident = "Panasonic Corporation CFSV8-2",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Panasonic Corporation"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "CFSV8-2"),
> + },
> + .driver_data = &quirk_cf_sv8,
> + },
> + {
> + .ident = "Panasonic Corporation CFRZ6-2",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Panasonic Corporation"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "CFRZ6-2"),
> + },
> + .driver_data = &quirk_cf_rz6,
> + },
> + {},
> +};
--
i.
^ permalink raw reply [flat|nested] 5+ messages in thread