Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help with getting SW_TABLET_MODE reporting working on the MSI Summit E16 Flip ? #77

Open
jwrdegoede opened this issue Dec 21, 2022 · 20 comments

Comments

@jwrdegoede
Copy link

Short self introduction I'm a Linux developer mostly working on hw-enablement for Linux laptops. I'm also the subsystem maintainer for kernel drivers under: drivers/platform/x86

I have been working with a user to get SW_TABLET_MODE reporting working on their MSI Summit E16 Flip A12UCT: https://gitlab.freedesktop.org/libinput/libinput/-/issues/822

Looking at the ACPI tables of that model, their is an intel-hid ACPI device (check for HIDD in dsdt.dsl) which should report if the 2-in-1 is folded into tablet-mode or being used in laptop mode. Specifically the bit of ACPI code below should cause 0xcc / 0xcd ACPI notifies to be send which should then get picked up by the https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/platform/x86/intel/hid.c code and translated into SW_TABLET_MODE input events:

    Scope (_SB.PC00.LPCB)
    {
...
        Device (EC)
        {
...
            Method (_Q84, 0, NotSerialized)  // _Qxx: EC Query, xx=0x00-0xFF
            {
                SCIC = 0x84
                DBG8 = 0x84
                If ((IUCE == One))
                {
                    If (MYEC)
                    {
                        CONV = ISHS /* \_SB_.PC00.LPCB.EC__.ISHS */
                        If (((OSYS >= 0x07DF) && ^^^^HIDD.BTLD))
                        {
                            If ((CONV == 0x03))
                            {
                                UPBT (0x06, Zero)
                                Notify (^^^^HIDD, 0xCC) // Hardware-Specific
                            }
                            ElseIf ((CONV == One))
                            {
                                UPBT (0x06, One)
                                Notify (^^^^HIDD, 0xCD) // Hardware-Specific
                            }
                        }
                        ElseIf (CondRefOf (\_SB.PC00.GFX0.IUEH))
                        {
                            ^^^GFX0.IUEH (0x06)
                        }
                    }
                    Else
                    {
                        UPBT (0x06, One)
                        Notify (^^^^HIDD, 0xCD) // Hardware-Specific
                    }

                    Notify (LID0, 0x80) // Status Change
                }
                Else
                {
                    Notify (LID0, 0x80) // Status Change
                }
            }

But it seems that for some reason the EC is never sending 0x84 events, so this code never gets executed by the kernel's ACPI interpreter and we never get the 0xCC / 0xCD notifies on the ACPI HIDD device.

@dmitry-s93 since you have quite a bit of experience with the MSI EC on these devices, I wonder if you have any insights in this?

@rottenpants466
Copy link
Contributor

rottenpants466 commented Dec 21, 2022

The user was me Hans 👍 (You got the hotkeys working btw! this will surely help other people too!!)

If i may, a while ago i also tried getting some help with other 2 people in order to solve this issue and others (battery thresholds):

@ThePBone https://github.com/ThePBone/msi-ec-modern
@BeardOverflow https://github.com/BeardOverflow/msi-ec (Original MSI ec author, not as active)

This may be useful.

In the meantime i have been using MControlCenter, all the features work in my laptop! Kudos to dmitry!

Edit: this may be useful too: @musikid https://github.com/musikid/acpi_ec

@rottenpants466
Copy link
Contributor

@jwrdegoede @teackot

So im still trying to find a way to fix this issue, i managed to install windows 11 on a separate ssd and i'm using this tool: https://github.com/ThePBone/MsiEcRamEditor

screenshot

Im trying to see if i can find anything in the right column when i flip the screen but when then list updates it usually shows 3 or 4 new entries so i don't know which corresponds with the screen flip.

@timschneeb
Copy link
Contributor

timschneeb commented Mar 15, 2023

Im trying to see if i can find anything in the right column when i flip the screen but when then list updates it usually shows 3 or 4 new entries so i don't know which corresponds with the screen flip.

@rottenpants466 That's probably caused by the real-time CPU & GPU info that is updated constantly in EC memory and litters the whole log on the right side.

You can click on 'Log options > Exclude addresses' in the program and enter those addresses containing the real-time data to prevent the log from getting spammed with irrelevant data.

@teackot
Copy link
Contributor

teackot commented Mar 15, 2023

I can say for sure that those that update even when you don't flip your screen are not what we're looking for

E.g. 0x68 is CPU temp

@rottenpants466
Copy link
Contributor

Thanks for responding.

So i noticed 2 new adresses that only appear when i flip the screen back and forth:

0xED
0xEE

screen

EE always appears when i flip the screen, ED most of the time

@teackot
Copy link
Contributor

teackot commented Mar 15, 2023

They're subsequent so I think they may be related in some way

Looking at this picture I see that 0xEE had its bit1 flipped and 0xED has 2 flipped bits

ED most of the time

Can it be a rotation sensor? Try rotating your laptop without flipping the screen (edit: it isn't a rotation sensor)

@rottenpants466
Copy link
Contributor

Rotation sensor works fine in Linux

Tried a couple of times ED only shows up like 80% of the time. EE always shows up. In the picture above the first ED/EE entries in red appeared when i flipped to tablet mode, the second ED/EE entries in red when i flipped back to "normal" mode

@teackot
Copy link
Contributor

teackot commented Mar 15, 2023

Hans wrote:

But it seems that for some reason the EC is never sending 0x84 event

He mentioned some 0x84 event and in the picture 0xED is getting set to 0x84 (in the second red pair)

In this issue in my EC table repo we figured out that 0xED gets changed when some sort of events are emitted (e.g. brightness up or down, USB-C connection)

Tried a couple of times ED only shows up like 80% of the time

I think 0xED is set to 0x84 when the screen is flipped. It doesn't show up all the time because the right column shows changes, so 0xED needs to first be set to some other value by another event for it to show up there

@teackot
Copy link
Contributor

teackot commented Mar 15, 2023

If ((CONV == 0x03))
{
UPBT (0x06, Zero)
Notify (^^^^HIDD, 0xCC) // Hardware-Specific
}
ElseIf ((CONV == One))
{
UPBT (0x06, One)
Notify (^^^^HIDD, 0xCD) // Hardware-Specific
}

CONV is compared to 0x03 and One (which I suppose means 0x01)

EC's 0xEE address is set to 0x03 and 0x01 when screen is flipped back and forth

@teackot
Copy link
Contributor

teackot commented Mar 15, 2023

@rottenpants466 can you please check if 0xED and/or 0xEE are changed in Linux when flipping the screen?

Specifically, you need to look for 0x84 in [0xED] and 0x01/0x03 in [0xEE]

@rottenpants466
Copy link
Contributor

@rottenpants466 can you please check if 0xED and/or 0xEE are changed in Linux when flipping the screen?

Specifically, you need to look for 0x84 in [0xED] and 0x01/0x03 in [0xEE]

Will check

Thank you 👍

@rottenpants466
Copy link
Contributor

Also since i'm testing this stuff on windows do you want me to test something else regarding the ec drivers @teackot ?

cheer

@teackot
Copy link
Contributor

teackot commented Mar 15, 2023

Also since i'm testing this stuff on windows do you want me to test something else regarding the ec drivers

I think we got all of your values on Linux, though you can test a couple more things: check if switching mute LED triggers the [0x2C] and if mic mute triggers [0x2B]

Also switching webcam should trigger [0x2E]

@rottenpants466
Copy link
Contributor

rottenpants466 commented Mar 15, 2023

Also since i'm testing this stuff on windows do you want me to test something else regarding the ec drivers

I think we got all of your values on Linux, though you can test a couple more things: check if switching mute LED triggers the [0x2C] and if mic mute triggers [0x2B]

Also switching webcam should trigger [0x2E]

Is there a specific area where i should look for 0x84 in [0xED] and 0x01/0x03 in [0xEE] and the leds/webcam?

There were some special keys that didn't do anything but hans managed to get that fixed:

https://bugzilla.kernel.org/show_bug.cgi?id=216824

systemd/systemd#25824

Screenshot_20230315_232831

Edit: It doesn't seem to trigger anything when flipping the screen in Linux

@rottenpants466
Copy link
Contributor

rottenpants466 commented Mar 16, 2023

It seems that other newer laptops might have the same problem and are using some new sensor still not supported in Linux:

https://forums.lenovo.com/t5/Lenovo-Yoga-Series-Laptops/Lenovo-Yoga-7-gen-7-amd-14ARB7-tablet-mode-change-WMI-interfaces/m-p/5171832

https://discussion.fedoraproject.org/t/sw-tablet-mode-on-yoga-l13-undetected-switch-manually/60935
linux-surface/linux-surface#735

https://github.com/alesya-h/linux_detect_tablet_mode

https://lwn.net/Articles/910415/

Is there a way to find the sensor in windows and extract information from it?

Edit: some more info that might be useful:

dotnet/maui#11135

https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-gpiobuttons-convertibleslatemode

I also found this windows app Sensor Explorer https://learn.microsoft.com/en-us/windows-hardware/drivers/sensors/testing-sensor-explorer will play around with it to see if i find anything relevant

Hans also tried to help me with that issue a while back: https://gitlab.freedesktop.org/libinput/libinput/-/issues/822

@rottenpants466
Copy link
Contributor

rottenpants466 commented Mar 17, 2023

@teackot i did an experiment where i reinstalled windows 11 on the other nvme drive. Booted to desktop without an internet connection with a fresh install and noticed a few things. By default with no drivers or anything else installed, no internet, the laptop is missing a few things:

  • No tablet mode detection;
  • Some function keys not working: mic mute, camera on/off, msi power modes and flip the screen 180º;
  • Sound and mute function key leds doesn't turn on/off when activated/deactivated.

Next i downloaded all the drivers from the MSI Website into a usb stick in fedora. After that i booted windows again and installed the drivers one at a time and checked the tablet mode detection and keys each time. By the end with all the drivers installed Windows still couldn't detect tablet mode when flipping the screen, some function keys didn't work and leds also did not work either.

Next i connected to the internet and updated everything with Windows Update, some remaining drivers were also available. After everything was installed i then tested again, tablet mode/function keys/leds were still not working.

Finally i installed MSI Center Pro and on the next restart and all of the sudden tablet mode was working as well the function keys and their leds. Tested again with the app closed and with no auto start on reboot and everything was still working.

So it seems MSI Center Pro is really necessary for a lot of functionalities :|

@rottenpants466
Copy link
Contributor

@teackot @jwrdegoede @ThePBone @dmitry-s93 I was checking this bug report on gitlab and there is a user who is working on a workaround to try to fix this issue on their Lenovo laptops:

https://lore.kernel.org/all/CAG4kvq9US=-NjyXFMzJYu2zCJryJWtOc7FGZbrewpgCDjdAkbg@mail.gmail.com/
https://lore.kernel.org/all/20230323025200.5462-1-kallmeyeras@gmail.com/

The actual patch:

--- a/drivers/platform/x86/lenovo-ymc.c
+++ b/drivers/platform/x86/lenovo-ymc.c
@@ -18,7 +18,7 @@
 #define LENOVO_YMC_QUERY_GUID	"09B0EE6E-C3FD-4243-8DA1-7911FF80BB8C"
 
 #define LENOVO_YMC_QUERY_INSTANCE 0
-#define LENOVO_YMC_QUERY_METHOD 0xAB
+#define LENOVO_YMC_QUERY_METHOD 0x01
 
 static bool ec_trigger __read_mostly;
 module_param(ec_trigger, bool, 0644);
@@ -103,6 +103,12 @@ static void lenovo_ymc_notify(struct wmi_device *wdev, union acpi_object *data)
 	lenovo_ymc_trigger_ec(wdev, priv);
 }
 
+static void lenovo_ymc_remove(struct wmi_device *wdev)
+{
+	struct lenovo_ymc_private *priv = dev_get_drvdata(&wdev->dev);
+	acpi_dev_put(priv->ec_acpi_dev);
+}
+
 static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
 {
 	struct input_dev *input_dev;
@@ -117,7 +123,7 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
 
 	if (ec_trigger) {
 		pr_debug("Lenovo YMC enable EC triggering.\n");
-		priv->ec_acpi_dev = acpi_dev_get_first_match_dev("VCP2004", NULL, -1);
+		priv->ec_acpi_dev = acpi_dev_get_first_match_dev("VPC2004", NULL, -1);
 		if (!priv->ec_acpi_dev) {
 			dev_err(&wdev->dev, "Could not find EC ACPI device.\n");
 			return -ENODEV;
@@ -151,7 +157,10 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
 
 	priv->input_dev = input_dev;
 	dev_set_drvdata(&wdev->dev, priv);
+
+	// Report the state for the first time on probe
 	lenovo_ymc_trigger_ec(wdev, priv);
+	lenovo_ymc_notify(wdev, NULL);
 	return 0;
 }
 
@@ -168,6 +177,7 @@ static struct wmi_driver lenovo_ymc_driver = {
 	.id_table = lenovo_ymc_wmi_id_table,
 	.probe = lenovo_ymc_probe,
 	.notify = lenovo_ymc_notify,
+	.remove = lenovo_ymc_remove,
 };
 
 module_wmi_driver(lenovo_ymc_driver);

Andrew Kallmeyer (1):
  platform/x86: Move ideapad ACPI helpers to a new header

Gergo Koteles (1):
  platform/x86: Add driver for Yoga Tablet Mode switch

 drivers/platform/x86/Kconfig          |  10 ++
 drivers/platform/x86/Makefile         |   1 +
 drivers/platform/x86/ideapad-laptop.c | 135 +------------------
 drivers/platform/x86/ideapad-laptop.h | 152 +++++++++++++++++++++
 drivers/platform/x86/lenovo-ymc.c     | 187 ++++++++++++++++++++++++++
 5 files changed, 351 insertions(+), 134 deletions(-)
 create mode 100644 drivers/platform/x86/ideapad-laptop.h
 create mode 100644 drivers/platform/x86/lenovo-ymc.c

-- 
2.40.0

Can something like this be used on our MSI laptops? i tried to apply this patch but then realised this might only work on Lenovo laptops.

cheers

@rottenpants466
Copy link
Contributor

Here i am again :)

In Windows there's this app from microsoft where i can check all the supported sensors on this device (check sensor attachments).

I tested all of the available sensors and it seems there's no sensor that detects tablet mode directly (like 0 or 1, On or OFF). I think in this particular case the tablet mode info comes from the orientation/inclination of the laptop itself and the screen itself (it seems there are at least 2 inclination sensors one on the laptop and the other one on the screen).

sensors 2

sensors

@jwrdegoede
Copy link
Author

If there are indeed 2 accelerometers then this is a known problem. We need someone to add support for this setup to iio-sensor-proxy, this is being tracked here:

https://gitlab.freedesktop.org/hadess/iio-sensor-proxy/-/issues/216

@rottenpants466
Copy link
Contributor

rottenpants466 commented Apr 13, 2023

Can something like this be used in our 2 in 1 MSI laptops?

https://github.com/lukas-w/yoga-usage-mode

https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=for-next&id=e82882cdd241b78d305df1441c624fbbbd07af05

From what i could gather, it creates a SW_TABLET_MODE device that then sends input to user-space.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants