From 665aa4e794d5530298f9fec4da5886c566ea0025 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Sun, 29 May 2022 13:46:12 +0200 Subject: kernel 5.17.11 --- SOURCES/Patchlist.changelog | 3 + SOURCES/kernel-aarch64-debug-fedora.config | 5 + SOURCES/kernel-aarch64-debug-rhel.config | 5 + SOURCES/kernel-aarch64-fedora.config | 5 + SOURCES/kernel-aarch64-rhel.config | 5 + SOURCES/kernel-armv7hl-debug-fedora.config | 5 + SOURCES/kernel-armv7hl-fedora.config | 5 + SOURCES/kernel-armv7hl-lpae-debug-fedora.config | 5 + SOURCES/kernel-armv7hl-lpae-fedora.config | 5 + SOURCES/kernel-ppc64le-debug-fedora.config | 5 + SOURCES/kernel-ppc64le-debug-rhel.config | 5 + SOURCES/kernel-ppc64le-fedora.config | 5 + SOURCES/kernel-ppc64le-rhel.config | 5 + SOURCES/kernel-s390x-debug-fedora.config | 5 + SOURCES/kernel-s390x-debug-rhel.config | 5 + SOURCES/kernel-s390x-fedora.config | 5 + SOURCES/kernel-s390x-rhel.config | 5 + SOURCES/kernel-s390x-zfcpdump-rhel.config | 5 + SOURCES/kernel-x86_64-debug-fedora.config | 5 + SOURCES/kernel-x86_64-debug-rhel.config | 5 + SOURCES/kernel-x86_64-fedora.config | 5 + SOURCES/kernel-x86_64-rhel.config | 5 + SOURCES/linux-surface.patch | 5723 ++++++++++++++++++----- SOURCES/patch-5.17-redhat.patch | 61 +- SOURCES/simpledrm-nvidia.patch | 87 - SPECS/kernel.spec | 31 +- 26 files changed, 4609 insertions(+), 1401 deletions(-) delete mode 100644 SOURCES/simpledrm-nvidia.patch diff --git a/SOURCES/Patchlist.changelog b/SOURCES/Patchlist.changelog index 174e803..2d1781f 100644 --- a/SOURCES/Patchlist.changelog +++ b/SOURCES/Patchlist.changelog @@ -1,3 +1,6 @@ +"https://gitlab.com/cki-project/kernel-ark/-/commit"/205bec68a0ea67b6bff6fea9603b7b8aeacc9d46 + 205bec68a0ea67b6bff6fea9603b7b8aeacc9d46 drivers/firmware: skip simpledrm if nvidia-drm.modeset=1 is set + "https://gitlab.com/cki-project/kernel-ark/-/commit"/8a35d9b408eeb4798a147fb76eb3f10368133de8 8a35d9b408eeb4798a147fb76eb3f10368133de8 efi: x86: Set the NX-compatibility flag in the PE header diff --git a/SOURCES/kernel-aarch64-debug-fedora.config b/SOURCES/kernel-aarch64-debug-fedora.config index 2c7833c..1606cf7 100644 --- a/SOURCES/kernel-aarch64-debug-fedora.config +++ b/SOURCES/kernel-aarch64-debug-fedora.config @@ -8690,7 +8690,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-aarch64-debug-rhel.config b/SOURCES/kernel-aarch64-debug-rhel.config index 15f15ac..50fa689 100644 --- a/SOURCES/kernel-aarch64-debug-rhel.config +++ b/SOURCES/kernel-aarch64-debug-rhel.config @@ -6882,7 +6882,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-aarch64-fedora.config b/SOURCES/kernel-aarch64-fedora.config index 5f17da1..29630dc 100644 --- a/SOURCES/kernel-aarch64-fedora.config +++ b/SOURCES/kernel-aarch64-fedora.config @@ -8663,7 +8663,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-aarch64-rhel.config b/SOURCES/kernel-aarch64-rhel.config index 065f98d..f4b65bf 100644 --- a/SOURCES/kernel-aarch64-rhel.config +++ b/SOURCES/kernel-aarch64-rhel.config @@ -6857,7 +6857,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-armv7hl-debug-fedora.config b/SOURCES/kernel-armv7hl-debug-fedora.config index 672f0be..52825d4 100644 --- a/SOURCES/kernel-armv7hl-debug-fedora.config +++ b/SOURCES/kernel-armv7hl-debug-fedora.config @@ -8910,7 +8910,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-armv7hl-fedora.config b/SOURCES/kernel-armv7hl-fedora.config index 92a6a8b..dbbac99 100644 --- a/SOURCES/kernel-armv7hl-fedora.config +++ b/SOURCES/kernel-armv7hl-fedora.config @@ -8884,7 +8884,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-armv7hl-lpae-debug-fedora.config b/SOURCES/kernel-armv7hl-lpae-debug-fedora.config index 9165701..f960594 100644 --- a/SOURCES/kernel-armv7hl-lpae-debug-fedora.config +++ b/SOURCES/kernel-armv7hl-lpae-debug-fedora.config @@ -8652,7 +8652,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-armv7hl-lpae-fedora.config b/SOURCES/kernel-armv7hl-lpae-fedora.config index dbb9949..800935b 100644 --- a/SOURCES/kernel-armv7hl-lpae-fedora.config +++ b/SOURCES/kernel-armv7hl-lpae-fedora.config @@ -8626,7 +8626,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-ppc64le-debug-fedora.config b/SOURCES/kernel-ppc64le-debug-fedora.config index 492f79e..d033a76 100644 --- a/SOURCES/kernel-ppc64le-debug-fedora.config +++ b/SOURCES/kernel-ppc64le-debug-fedora.config @@ -7447,7 +7447,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-ppc64le-debug-rhel.config b/SOURCES/kernel-ppc64le-debug-rhel.config index d8bdbb0..6d84f26 100644 --- a/SOURCES/kernel-ppc64le-debug-rhel.config +++ b/SOURCES/kernel-ppc64le-debug-rhel.config @@ -6645,7 +6645,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-ppc64le-fedora.config b/SOURCES/kernel-ppc64le-fedora.config index 8d6969d..7b6c577 100644 --- a/SOURCES/kernel-ppc64le-fedora.config +++ b/SOURCES/kernel-ppc64le-fedora.config @@ -7420,7 +7420,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-ppc64le-rhel.config b/SOURCES/kernel-ppc64le-rhel.config index ddefaa0..bd3aa18 100644 --- a/SOURCES/kernel-ppc64le-rhel.config +++ b/SOURCES/kernel-ppc64le-rhel.config @@ -6624,7 +6624,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-s390x-debug-fedora.config b/SOURCES/kernel-s390x-debug-fedora.config index 1ce9216..8fb3926 100644 --- a/SOURCES/kernel-s390x-debug-fedora.config +++ b/SOURCES/kernel-s390x-debug-fedora.config @@ -7403,7 +7403,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-s390x-debug-rhel.config b/SOURCES/kernel-s390x-debug-rhel.config index c98deed..bd0d5ee 100644 --- a/SOURCES/kernel-s390x-debug-rhel.config +++ b/SOURCES/kernel-s390x-debug-rhel.config @@ -6602,7 +6602,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-s390x-fedora.config b/SOURCES/kernel-s390x-fedora.config index 8014372..a8346e6 100644 --- a/SOURCES/kernel-s390x-fedora.config +++ b/SOURCES/kernel-s390x-fedora.config @@ -7376,7 +7376,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-s390x-rhel.config b/SOURCES/kernel-s390x-rhel.config index 606f9db..872d3bf 100644 --- a/SOURCES/kernel-s390x-rhel.config +++ b/SOURCES/kernel-s390x-rhel.config @@ -6581,7 +6581,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-s390x-zfcpdump-rhel.config b/SOURCES/kernel-s390x-zfcpdump-rhel.config index 158f57f..a8eba5a 100644 --- a/SOURCES/kernel-s390x-zfcpdump-rhel.config +++ b/SOURCES/kernel-s390x-zfcpdump-rhel.config @@ -6609,7 +6609,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-x86_64-debug-fedora.config b/SOURCES/kernel-x86_64-debug-fedora.config index 54034f0..80ca310 100644 --- a/SOURCES/kernel-x86_64-debug-fedora.config +++ b/SOURCES/kernel-x86_64-debug-fedora.config @@ -7940,7 +7940,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-x86_64-debug-rhel.config b/SOURCES/kernel-x86_64-debug-rhel.config index dd3c843..d38e73e 100644 --- a/SOURCES/kernel-x86_64-debug-rhel.config +++ b/SOURCES/kernel-x86_64-debug-rhel.config @@ -6912,7 +6912,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-x86_64-fedora.config b/SOURCES/kernel-x86_64-fedora.config index d1aeed8..7733147 100644 --- a/SOURCES/kernel-x86_64-fedora.config +++ b/SOURCES/kernel-x86_64-fedora.config @@ -7914,7 +7914,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/kernel-x86_64-rhel.config b/SOURCES/kernel-x86_64-rhel.config index 446bf4e..7e4ecde 100644 --- a/SOURCES/kernel-x86_64-rhel.config +++ b/SOURCES/kernel-x86_64-rhel.config @@ -6888,7 +6888,12 @@ CONFIG_I2C_NCT6775=m CONFIG_ZENIFY=y # device specific config +# Steam Deck CONFIG_STEAMDECK=y +# Microsoft Surface CONFIG_MISC_IPTS=m CONFIG_SURFACE_KIP_TABLET_SWITCH=m +CONFIG_SURFACE_AGGREGATOR_HUB=m CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y +CONFIG_VIDEO_DW9719=m + diff --git a/SOURCES/linux-surface.patch b/SOURCES/linux-surface.patch index 4b97e90..f36ed75 100644 --- a/SOURCES/linux-surface.patch +++ b/SOURCES/linux-surface.patch @@ -1,4 +1,4 @@ -From ec6fa26f04034a252e606d4cdc8097282c59ab18 Mon Sep 17 00:00:00 2001 +From 646a8f056267c0c6efe791753f05c202d5f991c1 Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Sun, 18 Oct 2020 16:42:44 +0900 Subject: [PATCH] (surface3-oemb) add DMI matches for Surface 3 with broken DMI @@ -97,9 +97,9 @@ index c60a5e8e7bc9..e947133a2c36 100644 }; -- -2.36.0 +2.36.1 -From 1395350fc7351ab5a75541dd444b9321ab51642a Mon Sep 17 00:00:00 2001 +From 8d5bbcb596dc777e691b738c90fdde519d5ff70b Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Tue, 29 Sep 2020 17:32:22 +0900 Subject: [PATCH] mwifiex: pcie: add reset_wsid quirk for Surface 3 @@ -282,9 +282,9 @@ index 8ec4176d698f..25370c5a4f59 100644 int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev); +int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev); -- -2.36.0 +2.36.1 -From 312dfdce8be446cbe3fc1fb49754057218e2c7bd Mon Sep 17 00:00:00 2001 +From aa1d32ead69fc367cfe67296dda751a5e40b342f Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Wed, 30 Sep 2020 18:08:24 +0900 Subject: [PATCH] mwifiex: pcie: (OEMB) add quirk for Surface 3 with broken DMI @@ -344,9 +344,9 @@ index 563dd0d5ac79..32e2f000e57b 100644 }; -- -2.36.0 +2.36.1 -From 91a301f7fd782acf695910c618edcb98c062ed99 Mon Sep 17 00:00:00 2001 +From 4ac41e0c2d8fe11f20a5f79a0bfe0f56db7a5f2e Mon Sep 17 00:00:00 2001 From: Tsuchiya Yuto Date: Sun, 4 Oct 2020 00:11:49 +0900 Subject: [PATCH] mwifiex: pcie: disable bridge_d3 for Surface gen4+ @@ -499,9 +499,9 @@ index 25370c5a4f59..a1de111ad1db 100644 void mwifiex_initialize_quirks(struct pcie_service_card *card); int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev); -- -2.36.0 +2.36.1 -From 1febd99bd24be85092ba5ddbf04cac8d9deab2c0 Mon Sep 17 00:00:00 2001 +From bfcc84af31034dbdd24013dc9a26abe285b40f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Tue, 3 Nov 2020 13:28:04 +0100 Subject: [PATCH] mwifiex: Add quirk resetting the PCI bridge on MS Surface @@ -666,9 +666,9 @@ index a1de111ad1db..0e429779bb04 100644 void mwifiex_initialize_quirks(struct pcie_service_card *card); int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev); -- -2.36.0 +2.36.1 -From 8c6862539a41224f764f06e5f0c7284770edc3f4 Mon Sep 17 00:00:00 2001 +From 58c6afc494c4e3b99d616ecbcaaae4fc2a2793f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Thu, 25 Mar 2021 11:33:02 +0100 Subject: [PATCH] Bluetooth: btusb: Lower passive lescan interval on Marvell @@ -744,9 +744,9 @@ index 42234d5f602d..72202a744564 100644 (id->driver_info & BTUSB_MEDIATEK)) { hdev->setup = btusb_mtk_setup; -- -2.36.0 +2.36.1 -From 921b3bdd8d6d963f5ea108a699ef6f70a3709acd Mon Sep 17 00:00:00 2001 +From 2fca431e32e851a81ec218ef3dc87563d7cd0e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Tue, 10 Nov 2020 12:49:56 +0100 Subject: [PATCH] mwifiex: Use non-posted PCI register writes @@ -801,9 +801,9 @@ index 24bcd22a2618..b4ad0113a035 100644 } -- -2.36.0 +2.36.1 -From 1e8468a42b52eb369a70003f99dde7b16846c5e2 Mon Sep 17 00:00:00 2001 +From d4c4b533922f980a4cf0ad48db72506b3cba3a01 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Sat, 27 Feb 2021 00:45:52 +0100 Subject: [PATCH] ath10k: Add module parameters to override board files @@ -922,9 +922,9 @@ index 8f5b8eb368fa..80c1bac732bc 100644 ret = firmware_request_nowarn(&fw, filename, ar->dev); ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n", -- -2.36.0 +2.36.1 -From 5f96f9f986f4177c1072baa7f3ab5f134cf20415 Mon Sep 17 00:00:00 2001 +From e2a9cc1c420b8f9584c85914b6b8c8cb38b2fecc Mon Sep 17 00:00:00 2001 From: Dorian Stoll Date: Thu, 30 Jul 2020 13:21:53 +0200 Subject: [PATCH] misc: mei: Add missing IPTS device IDs @@ -960,9 +960,9 @@ index a738253dbd05..4e1c3fe09e53 100644 {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)}, -- -2.36.0 +2.36.1 -From fce727fc65f22335a65f82446d045da06cae42c6 Mon Sep 17 00:00:00 2001 +From c7d40fe3f9a803b17f8529caa7bc4b58c0a2e66a Mon Sep 17 00:00:00 2001 From: Dorian Stoll Date: Thu, 6 Aug 2020 11:20:41 +0200 Subject: [PATCH] misc: Add support for Intel Precise Touch & Stylus @@ -2425,118 +2425,9 @@ index 000000000000..53fb86a88f97 + +#endif /* _IPTS_UAPI_H_ */ -- -2.36.0 +2.36.1 -From db68833d47e0d5ee2bc2003b9e410a4f672aa43a Mon Sep 17 00:00:00 2001 -From: zouxiaoh -Date: Fri, 25 Jun 2021 08:52:59 +0800 -Subject: [PATCH] iommu: intel-ipu: use IOMMU passthrough mode for Intel IPUs - -Intel IPU(Image Processing Unit) has its own (IO)MMU hardware, -The IPU driver allocates its own page table that is not mapped -via the DMA, and thus the Intel IOMMU driver blocks access giving -this error: DMAR: DRHD: handling fault status reg 3 DMAR: -[DMA Read] Request device [00:05.0] PASID ffffffff -fault addr 76406000 [fault reason 06] PTE Read access is not set -As IPU is not an external facing device which is not risky, so use -IOMMU passthrough mode for Intel IPUs. - -Change-Id: I6dcccdadac308cf42e20a18e1b593381391e3e6b -Depends-On: Iacd67578e8c6a9b9ac73285f52b4081b72fb68a6 -Tracked-On: #JIITL8-411 -Signed-off-by: Bingbu Cao -Signed-off-by: zouxiaoh -Signed-off-by: Xu Chongyang -Patchset: ipts ---- - drivers/iommu/intel/iommu.c | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c -index 5b196cfe9ed2..a5fc95dbb06d 100644 ---- a/drivers/iommu/intel/iommu.c -+++ b/drivers/iommu/intel/iommu.c -@@ -57,6 +57,12 @@ - #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) - #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB) - #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) -+#define IS_INTEL_IPU(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \ -+ ((pdev)->device == 0x9a19 || \ -+ (pdev)->device == 0x9a39 || \ -+ (pdev)->device == 0x4e19 || \ -+ (pdev)->device == 0x465d || \ -+ (pdev)->device == 0x1919)) - #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) - - #define IOAPIC_RANGE_START (0xfee00000) -@@ -332,12 +338,14 @@ int intel_iommu_enabled = 0; - EXPORT_SYMBOL_GPL(intel_iommu_enabled); - - static int dmar_map_gfx = 1; -+static int dmar_map_ipu = 1; - static int intel_iommu_superpage = 1; - static int iommu_identity_mapping; - static int iommu_skip_te_disable; - - #define IDENTMAP_GFX 2 - #define IDENTMAP_AZALIA 4 -+#define IDENTMAP_IPU 8 - - int intel_iommu_gfx_mapped; - EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); -@@ -2966,6 +2974,9 @@ static int device_def_domain_type(struct device *dev) - - if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev)) - return IOMMU_DOMAIN_IDENTITY; -+ -+ if ((iommu_identity_mapping & IDENTMAP_IPU) && IS_INTEL_IPU(pdev)) -+ return IOMMU_DOMAIN_IDENTITY; - } - - return 0; -@@ -3402,6 +3413,9 @@ static int __init init_dmars(void) - if (!dmar_map_gfx) - iommu_identity_mapping |= IDENTMAP_GFX; - -+ if (!dmar_map_ipu) -+ iommu_identity_mapping |= IDENTMAP_IPU; -+ - check_tylersburg_isoch(); - - ret = si_domain_init(hw_pass_through); -@@ -5643,6 +5657,18 @@ static void quirk_iommu_igfx(struct pci_dev *dev) - dmar_map_gfx = 0; - } - -+static void quirk_iommu_ipu(struct pci_dev *dev) -+{ -+ if (!IS_INTEL_IPU(dev)) -+ return; -+ -+ if (risky_device(dev)) -+ return; -+ -+ pci_info(dev, "Passthrough IOMMU for integrated Intel IPU\n"); -+ dmar_map_ipu = 0; -+} -+ - /* G4x/GM45 integrated gfx dmar support is totally busted. */ - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx); -@@ -5678,6 +5704,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx); - -+/* disable IPU dmar support */ -+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_iommu_ipu); -+ - static void quirk_iommu_rwbf(struct pci_dev *dev) - { - if (risky_device(dev)) --- -2.36.0 - -From b3fbdb5c4552d9d98715e19ca13302615e7aca80 Mon Sep 17 00:00:00 2001 +From af203d5ea529b8d75dfcb53b993bd7c060d258a2 Mon Sep 17 00:00:00 2001 From: Liban Hannan Date: Tue, 12 Apr 2022 23:31:12 +0100 Subject: [PATCH] iommu: ipts: use IOMMU passthrough mode for IPTS @@ -2558,37 +2449,36 @@ Patchset: ipts 1 file changed, 24 insertions(+) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c -index a5fc95dbb06d..b3f6213048fd 100644 +index ab2273300346..a91eed82bb39 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c -@@ -63,6 +63,8 @@ - (pdev)->device == 0x4e19 || \ - (pdev)->device == 0x465d || \ - (pdev)->device == 0x1919)) +@@ -57,6 +57,8 @@ + #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) + #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB) + #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) +#define IS_IPTS(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \ + ((pdev)->device == 0x9d3e)) #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) #define IOAPIC_RANGE_START (0xfee00000) -@@ -339,6 +341,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_enabled); +@@ -332,12 +334,14 @@ int intel_iommu_enabled = 0; + EXPORT_SYMBOL_GPL(intel_iommu_enabled); static int dmar_map_gfx = 1; - static int dmar_map_ipu = 1; +static int dmar_map_ipts = 1; static int intel_iommu_superpage = 1; static int iommu_identity_mapping; static int iommu_skip_te_disable; -@@ -346,6 +349,7 @@ static int iommu_skip_te_disable; + #define IDENTMAP_GFX 2 #define IDENTMAP_AZALIA 4 - #define IDENTMAP_IPU 8 +#define IDENTMAP_IPTS 16 int intel_iommu_gfx_mapped; EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); -@@ -2977,6 +2981,9 @@ static int device_def_domain_type(struct device *dev) +@@ -2987,6 +2991,9 @@ static int device_def_domain_type(struct device *dev) - if ((iommu_identity_mapping & IDENTMAP_IPU) && IS_INTEL_IPU(pdev)) + if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev)) return IOMMU_DOMAIN_IDENTITY; + + if ((iommu_identity_mapping & IDENTMAP_IPTS) && IS_IPTS(pdev)) @@ -2596,9 +2486,9 @@ index a5fc95dbb06d..b3f6213048fd 100644 } return 0; -@@ -3416,6 +3423,9 @@ static int __init init_dmars(void) - if (!dmar_map_ipu) - iommu_identity_mapping |= IDENTMAP_IPU; +@@ -3423,6 +3430,9 @@ static int __init init_dmars(void) + if (!dmar_map_gfx) + iommu_identity_mapping |= IDENTMAP_GFX; + if (!dmar_map_ipts) + iommu_identity_mapping |= IDENTMAP_IPTS; @@ -2606,8 +2496,8 @@ index a5fc95dbb06d..b3f6213048fd 100644 check_tylersburg_isoch(); ret = si_domain_init(hw_pass_through); -@@ -5669,6 +5679,17 @@ static void quirk_iommu_ipu(struct pci_dev *dev) - dmar_map_ipu = 0; +@@ -5664,6 +5674,17 @@ static void quirk_iommu_igfx(struct pci_dev *dev) + dmar_map_gfx = 0; } +static void quirk_iommu_ipts(struct pci_dev *dev) @@ -2624,9 +2514,9 @@ index a5fc95dbb06d..b3f6213048fd 100644 /* G4x/GM45 integrated gfx dmar support is totally busted. */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx); -@@ -5707,6 +5728,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx); - /* disable IPU dmar support */ - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_iommu_ipu); +@@ -5699,6 +5720,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx); +/* disable IPTS dmar support */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9D3E, quirk_iommu_ipts); @@ -2635,9 +2525,9 @@ index a5fc95dbb06d..b3f6213048fd 100644 { if (risky_device(dev)) -- -2.36.0 +2.36.1 -From 2bb8c3daadfa4daa1f2d0f35b7753f850d0f0b62 Mon Sep 17 00:00:00 2001 +From a992351b539f71c2d037d717d09052d2a7c454fc Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Tue, 8 Jun 2021 00:24:47 +0200 Subject: [PATCH] platform/surface: aggregator: Allow devices to be marked as @@ -2663,24 +2553,9 @@ attempts should be avoided. Signed-off-by: Maximilian Luz Patchset: surface-sam --- - drivers/platform/surface/aggregator/bus.c | 3 ++ include/linux/surface_aggregator/device.h | 48 +++++++++++++++++++++-- - 2 files changed, 48 insertions(+), 3 deletions(-) + 1 file changed, 45 insertions(+), 3 deletions(-) -diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c -index abbbb5b08b07..2b003dcbfc4b 100644 ---- a/drivers/platform/surface/aggregator/bus.c -+++ b/drivers/platform/surface/aggregator/bus.c -@@ -388,6 +388,9 @@ void ssam_remove_clients(struct device *dev) - } - EXPORT_SYMBOL_GPL(ssam_remove_clients); - -+ -+/* -- Bus registration. ----------------------------------------------------- */ -+ - /** - * ssam_bus_register() - Register and set-up the SSAM client device bus. - */ diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h index cc257097eb05..491aa7e9f4bc 100644 --- a/include/linux/surface_aggregator/device.h @@ -2756,9 +2631,9 @@ index cc257097eb05..491aa7e9f4bc 100644 * ssam_device_get() - Increment reference count of SSAM client device. * @sdev: The device to increment the reference count of. -- -2.36.0 +2.36.1 -From e1da5a5135346e7091651f7fe2aa8c43b9d03f7d Mon Sep 17 00:00:00 2001 +From 8c9b27fdeb07fd4c83bb0d9d79776f21640d39d6 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Tue, 8 Jun 2021 00:48:22 +0200 Subject: [PATCH] platform/surface: aggregator: Allow notifiers to avoid @@ -2769,7 +2644,7 @@ communication attempts with those devices may fail and time out. This can even extend to event notifiers, due to which timeouts may occur during device removal, slowing down that process. -Add a flag to the notifier unregister function that allows skipping +Add a parameter to the notifier unregister function that allows skipping communication with the EC to prevent this. Furthermore, add wrappers for registering and unregistering notifiers belonging to SSAM client devices that automatically check if the device has been marked as hot-removed @@ -2783,10 +2658,10 @@ Signed-off-by: Maximilian Luz Patchset: surface-sam --- .../driver-api/surface_aggregator/client.rst | 6 +- - .../platform/surface/aggregator/controller.c | 53 ++++++++++------ - include/linux/surface_aggregator/controller.h | 24 +++++++- - include/linux/surface_aggregator/device.h | 60 +++++++++++++++++++ - 4 files changed, 122 insertions(+), 21 deletions(-) + .../platform/surface/aggregator/controller.c | 53 ++++++++++----- + include/linux/surface_aggregator/controller.h | 24 ++++++- + include/linux/surface_aggregator/device.h | 66 +++++++++++++++++++ + 4 files changed, 128 insertions(+), 21 deletions(-) diff --git a/Documentation/driver-api/surface_aggregator/client.rst b/Documentation/driver-api/surface_aggregator/client.rst index e519d374c378..27f95abdbe99 100644 @@ -2974,10 +2849,10 @@ index 74bfdffaf7b0..50a2b4926c06 100644 int ssam_controller_event_enable(struct ssam_controller *ctrl, struct ssam_event_registry reg, diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h -index 491aa7e9f4bc..16816c34da3e 100644 +index 491aa7e9f4bc..ad245c6b00d0 100644 --- a/include/linux/surface_aggregator/device.h +++ b/include/linux/surface_aggregator/device.h -@@ -472,4 +472,64 @@ static inline void ssam_remove_clients(struct device *dev) {} +@@ -472,4 +472,70 @@ static inline void ssam_remove_clients(struct device *dev) {} sdev->uid.instance, ret); \ } @@ -3010,6 +2885,12 @@ index 491aa7e9f4bc..16816c34da3e 100644 +static inline int ssam_device_notifier_register(struct ssam_device *sdev, + struct ssam_event_notifier *n) +{ ++ /* ++ * Note that this check does not provide any guarantees whatsoever as ++ * hot-removal could happen at any point and we can't protect against ++ * it. Nevertheless, if we can detect hot-removal, bail early to avoid ++ * communication timeouts. ++ */ + if (ssam_device_is_hot_removed(sdev)) + return -ENODEV; + @@ -3043,9 +2924,9 @@ index 491aa7e9f4bc..16816c34da3e 100644 + #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */ -- -2.36.0 +2.36.1 -From bf9269161d0e15076508e0ca776a31d860eacb7f Mon Sep 17 00:00:00 2001 +From 9c5a46d6a755d4c9546f44a4e13ef5a92bc98b2d Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Tue, 8 Jun 2021 01:20:49 +0200 Subject: [PATCH] platform/surface: aggregator_registry: Use client device @@ -3092,9 +2973,9 @@ index ce2bd88feeaa..9f630e890ff7 100644 ssam_remove_clients(&sdev->dev); } -- -2.36.0 +2.36.1 -From 7dffc0d5aa0b675201815f0db11d4207ed1bcf47 Mon Sep 17 00:00:00 2001 +From 86e1009150f92b4e756f6be81e80d45a42a9d497 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Thu, 28 Oct 2021 03:37:06 +0200 Subject: [PATCH] power/supply: surface_charger: Use client device wrappers for @@ -3132,9 +3013,9 @@ index a060c36c7766..59182d55742d 100644 static const struct spwr_psy_properties spwr_psy_props_adp1 = { -- -2.36.0 +2.36.1 -From bf04f91eb86cd24faed47f078d4c7cba0d3afb0a Mon Sep 17 00:00:00 2001 +From 033434def6261f801001c8d76b4a525b33b77372 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Thu, 28 Oct 2021 03:38:09 +0200 Subject: [PATCH] power/supply: surface_battery: Use client device wrappers for @@ -3172,9 +3053,9 @@ index 5ec2e6bb2465..540707882bb0 100644 } -- -2.36.0 +2.36.1 -From ec5de9e26ab336abeb4510101843ca9215f306ac Mon Sep 17 00:00:00 2001 +From 2971cc213e3adb104ac7de5a0feff4237a255166 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Tue, 8 Jun 2021 01:33:02 +0200 Subject: [PATCH] HID: surface-hid: Add support for hot-removal @@ -3186,8 +3067,8 @@ be avoided as it may fail and time out. While the device will be removed as soon as we detect hot-removal, communication may still occur during teardown, especially when unregistering notifiers. -While hot-removal is a surprise event that can happen any time, try to -avoid communication as much as possible once it has been detected to +While hot-removal is a surprise event that can happen at any time, try +to avoid communication as much as possible once it has been detected to prevent timeouts that can slow down device removal and cause issues, e.g. when quickly re-attaching the device. @@ -3283,9 +3164,9 @@ index e46330b2e561..87637f813de2 100644 return shid->ops.output_report(shid, reportnum, buf, len); -- -2.36.0 +2.36.1 -From 4bdf54b718375e303f8fe6745ffa90c4b153e20c Mon Sep 17 00:00:00 2001 +From f579f070fff7d5245cc08e08f888e2522ac62024 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Sun, 31 Oct 2021 12:34:08 +0100 Subject: [PATCH] platform/surface: aggregator: Add comment for KIP subsystem @@ -3308,7 +3189,7 @@ Patchset: surface-sam 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h -index c3de43edcffa..d1efac85caf1 100644 +index c3de43edcffa..26b95ec12733 100644 --- a/include/linux/surface_aggregator/serial_hub.h +++ b/include/linux/surface_aggregator/serial_hub.h @@ -306,7 +306,7 @@ enum ssam_ssh_tc { @@ -3316,239 +3197,189 @@ index c3de43edcffa..d1efac85caf1 100644 SSAM_SSH_TC_TCL = 0x0c, SSAM_SSH_TC_SFL = 0x0d, - SSAM_SSH_TC_KIP = 0x0e, -+ SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */ ++ SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */ SSAM_SSH_TC_EXT = 0x0f, SSAM_SSH_TC_BLD = 0x10, SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */ -- -2.36.0 +2.36.1 -From b05a57a23fb0dce8c1be11eda511116493d1e114 Mon Sep 17 00:00:00 2001 +From 8102d2904cbbddf212983a946dcbd3612dde060a Mon Sep 17 00:00:00 2001 From: Maximilian Luz -Date: Sun, 10 Oct 2021 23:56:23 +0200 -Subject: [PATCH] platform/surface: aggregator_registry: Add KIP device hub - -Add a Surface System Aggregator Module (SSAM) client device hub for -hot-removable devices managed via the KIP subsystem. - -The KIP subsystem (full name unknown, abbreviation has been obtained -through reverse engineering) is a subsystem that manages hot-removable -SSAM client devices. Specifically, it manages HID input devices -contained in the detachable keyboard cover of the Surface Pro 8 and -Surface Pro X. - -To properly handle detachable devices, we need to remove their kernel -representation when the physical device has been detached and (re-)add -and (re-)initialize said representation when the physical device has -been (re-)attached. Note that we need to hot-remove those devices, as -communication (especially during event notifier unregistration) may time -out when the physical device is no longer present, which would lead to -an unnecessary delay. This delay might become problematic when devices -are detached and re-attached quickly. - -The KIP subsystem handles a single group of devices (e.g. all devices -contained in the keyboard cover) and cannot handle devices individually. -Thus we model it as a client device hub, which removes all devices -contained under it once removal of the hub (e.g. keyboard cover) has -been detected and (re-)adds all devices once the physical hub device has -been (re-)attached. +Date: Fri, 29 Apr 2022 22:42:32 +0200 +Subject: [PATCH] platform/surface: aggregator_registry: Generify subsystem hub + functionality + +The Surface System Aggregator Module (SSAM) has multiple subsystems that +can manage detachable devices. At the moment, we only support the "base" +(BAS/0x11) subsystem, which is used on the Surface Book 3 to manage +devices (including keyboard, touchpad, and secondary battery) connected +to the base of the device. + +The Surface Pro 8 has a new type-cover with keyboard and touchpad, which +is managed via the KIP/0x0e subsystem. The general procedure is the +same, but with slightly different events and setup. To make +implementation of the KIP hub easier and prevent duplication, generify +the parts of the base hub that we can use for the KIP hub (or any +potential future subsystem hubs). + +This also switches over to use the newly introduced "hot-remove" +functionality, which should prevent communication issues when devices +have been detached. + +Lastly, also drop the undocumented and unused sysfs "state" attribute of +the base hub. It has at best been useful for debugging. Signed-off-by: Maximilian Luz Patchset: surface-sam --- - .../surface/surface_aggregator_registry.c | 247 +++++++++++++++++- - 1 file changed, 245 insertions(+), 2 deletions(-) + .../surface/surface_aggregator_registry.c | 269 ++++++++++-------- + 1 file changed, 153 insertions(+), 116 deletions(-) diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c -index 9f630e890ff7..4838ce6519a6 100644 +index 9f630e890ff7..09cbeee2428b 100644 --- a/drivers/platform/surface/surface_aggregator_registry.c +++ b/drivers/platform/surface/surface_aggregator_registry.c -@@ -514,6 +514,237 @@ static struct ssam_device_driver ssam_base_hub_driver = { - }; +@@ -308,30 +308,159 @@ static int ssam_hub_register_clients(struct device *parent, struct ssam_controll + } -+/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */ -+ -+/* -+ * Some devices may need a bit of time to be fully usable after being -+ * (re-)connected. This delay has been determined via experimentation. -+ */ -+#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250) -+ -+#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c -+ -+enum ssam_kip_hub_state { -+ SSAM_KIP_HUB_UNINITIALIZED, -+ SSAM_KIP_HUB_CONNECTED, -+ SSAM_KIP_HUB_DISCONNECTED, -+}; -+ -+struct ssam_kip_hub { -+ struct ssam_device *sdev; -+ -+ enum ssam_kip_hub_state state; -+ struct delayed_work update_work; -+ -+ struct ssam_event_notifier notif; -+}; -+ -+SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, { -+ .target_category = SSAM_SSH_TC_KIP, -+ .target_id = 0x01, -+ .command_id = 0x2c, -+ .instance_id = 0x00, -+}); -+ -+static int ssam_kip_get_connection_state(struct ssam_kip_hub *hub, enum ssam_kip_hub_state *state) -+{ -+ int status; -+ u8 connected; -+ -+ status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected); -+ if (status < 0) { -+ dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status); -+ return status; -+ } -+ -+ *state = connected ? SSAM_KIP_HUB_CONNECTED : SSAM_KIP_HUB_DISCONNECTED; -+ return 0; -+} -+ -+static ssize_t ssam_kip_hub_state_show(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct ssam_kip_hub *hub = dev_get_drvdata(dev); -+ const char *state; -+ -+ switch (hub->state) { -+ case SSAM_KIP_HUB_UNINITIALIZED: -+ state = "uninitialized"; -+ break; -+ -+ case SSAM_KIP_HUB_CONNECTED: -+ state = "connected"; -+ break; -+ -+ case SSAM_KIP_HUB_DISCONNECTED: -+ state = "disconnected"; -+ break; -+ -+ default: -+ /* -+ * Any value not handled in the above cases is invalid and -+ * should never have been set. Thus this case should be -+ * impossible to reach. -+ */ -+ WARN(1, "invalid KIP hub state: %d\n", hub->state); -+ state = ""; -+ break; -+ } -+ -+ return sysfs_emit(buf, "%s\n", state); -+} -+ -+static struct device_attribute ssam_kip_hub_attr_state = -+ __ATTR(state, 0444, ssam_kip_hub_state_show, NULL); -+ -+static struct attribute *ssam_kip_hub_attrs[] = { -+ &ssam_kip_hub_attr_state.attr, -+ NULL, -+}; -+ -+static const struct attribute_group ssam_kip_hub_group = { -+ .attrs = ssam_kip_hub_attrs, +-/* -- SSAM base-hub driver. ------------------------------------------------- */ ++/* -- SSAM generic subsystem hub driver framework. -------------------------- */ + +-/* +- * Some devices (especially battery) may need a bit of time to be fully usable +- * after being (re-)connected. This delay has been determined via +- * experimentation. +- */ +-#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500) ++enum ssam_hub_state { ++ SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */ ++ SSAM_HUB_CONNECTED, ++ SSAM_HUB_DISCONNECTED, +}; + +-enum ssam_base_hub_state { +- SSAM_BASE_HUB_UNINITIALIZED, +- SSAM_BASE_HUB_CONNECTED, +- SSAM_BASE_HUB_DISCONNECTED, ++enum ssam_hub_flags { ++ SSAM_HUB_HOT_REMOVED, + }; + +-struct ssam_base_hub { ++struct ssam_hub { + struct ssam_device *sdev; + +- enum ssam_base_hub_state state; ++ enum ssam_hub_state state; ++ unsigned long flags; + -+static int ssam_kip_hub_mark_hot_removed(struct device *dev, void *_data) -+{ -+ struct ssam_device *sdev = to_ssam_device(dev); -+ -+ if (is_ssam_device(dev)) -+ ssam_device_mark_hot_removed(sdev); -+ -+ return 0; -+} + struct delayed_work update_work; ++ unsigned long connect_delay; + + struct ssam_event_notifier notif; + -+static void ssam_kip_hub_update_workfn(struct work_struct *work) ++ int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state); + }; + ++static void ssam_hub_update_workfn(struct work_struct *work) +{ -+ struct ssam_kip_hub *hub = container_of(work, struct ssam_kip_hub, update_work.work); ++ struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work); + struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev); -+ enum ssam_kip_hub_state state; ++ enum ssam_hub_state state; + int status = 0; + -+ status = ssam_kip_get_connection_state(hub, &state); ++ status = hub->get_state(hub, &state); + if (status) + return; + ++ /* ++ * There is a small possibility that hub devices were hot-removed and ++ * re-added before we were able to remove them here. In that case, both ++ * the state returned by get_state() and the state of the hub will ++ * equal SSAM_HUB_CONNECTED and we would bail early below, which would ++ * leave child devices without proper (re-)initialization and the ++ * hot-remove flag set. ++ * ++ * Therefore, we check whether devices have been hot-removed via an ++ * additional flag on the hub and, in this case, override the returned ++ * hub state. In case of a missed disconnect (i.e. get_state returned ++ * "connected"), we further need to re-schedule this work (with the ++ * appropriate delay) as the actual connect work submission might have ++ * been merged with this one. ++ * ++ * This then leads to one of two cases: Either we submit an unnecessary ++ * work item (which will get ignored via either the queue or the state ++ * checks) or, in the unlikely case that the work is actually required, ++ * double the normal connect delay. ++ */ ++ if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) { ++ if (state == SSAM_HUB_CONNECTED) ++ schedule_delayed_work(&hub->update_work, hub->connect_delay); ++ ++ state = SSAM_HUB_DISCONNECTED; ++ } ++ + if (hub->state == state) + return; + hub->state = state; + -+ if (hub->state == SSAM_KIP_HUB_CONNECTED) ++ if (hub->state == SSAM_HUB_CONNECTED) + status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node); + else + ssam_remove_clients(&hub->sdev->dev); + + if (status) -+ dev_err(&hub->sdev->dev, "failed to update KIP-hub devices: %d\n", status); ++ dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status); +} + -+static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) ++static int ssam_hub_mark_hot_removed(struct device *dev, void *_data) +{ -+ struct ssam_kip_hub *hub = container_of(nf, struct ssam_kip_hub, notif); -+ unsigned long delay; ++ struct ssam_device *sdev = to_ssam_device(dev); + -+ if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION) -+ return 0; /* Return "unhandled". */ ++ if (is_ssam_device(dev)) ++ ssam_device_mark_hot_removed(sdev); + -+ if (event->length < 1) { -+ dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length); -+ return 0; -+ } ++ return 0; ++} ++ ++static void ssam_hub_update(struct ssam_hub *hub, bool connected) ++{ ++ unsigned long delay; + -+ /* Mark devices as hot-removed before we remove any */ -+ if (!event->data[0]) -+ device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_kip_hub_mark_hot_removed); ++ /* Mark devices as hot-removed before we remove any. */ ++ if (!connected) { ++ set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags); ++ device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed); ++ } + + /* -+ * Delay update when KIP devices are being connected to give devices/EC -+ * some time to set up. ++ * Delay update when the base/keyboard cover is being connected to give ++ * devices/EC some time to set up. + */ -+ delay = event->data[0] ? SSAM_KIP_UPDATE_CONNECT_DELAY : 0; ++ delay = connected ? hub->connect_delay : 0; + + schedule_delayed_work(&hub->update_work, delay); -+ return SSAM_NOTIF_HANDLED; +} + -+static int __maybe_unused ssam_kip_hub_resume(struct device *dev) ++static int __maybe_unused ssam_hub_resume(struct device *dev) +{ -+ struct ssam_kip_hub *hub = dev_get_drvdata(dev); ++ struct ssam_hub *hub = dev_get_drvdata(dev); + + schedule_delayed_work(&hub->update_work, 0); + return 0; +} -+static SIMPLE_DEV_PM_OPS(ssam_kip_hub_pm_ops, NULL, ssam_kip_hub_resume); ++static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume); + -+static int ssam_kip_hub_probe(struct ssam_device *sdev) ++static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub) +{ -+ struct ssam_kip_hub *hub; + int status; + -+ hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL); -+ if (!hub) -+ return -ENOMEM; -+ + hub->sdev = sdev; -+ hub->state = SSAM_KIP_HUB_UNINITIALIZED; ++ hub->state = SSAM_HUB_UNINITIALIZED; + -+ hub->notif.base.priority = INT_MAX; /* This notifier should run first. */ -+ hub->notif.base.fn = ssam_kip_hub_notif; -+ hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM; -+ hub->notif.event.id.target_category = SSAM_SSH_TC_KIP, -+ hub->notif.event.id.instance = 0, -+ hub->notif.event.mask = SSAM_EVENT_MASK_TARGET; -+ hub->notif.event.flags = SSAM_EVENT_SEQUENCED; -+ -+ INIT_DELAYED_WORK(&hub->update_work, ssam_kip_hub_update_workfn); ++ INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn); + + ssam_device_set_drvdata(sdev, hub); + @@ -3556,29 +3387,314 @@ index 9f630e890ff7..4838ce6519a6 100644 + if (status) + return status; + -+ status = sysfs_create_group(&sdev->dev.kobj, &ssam_kip_hub_group); -+ if (status) -+ goto err; -+ + schedule_delayed_work(&hub->update_work, 0); + return 0; ++} ++ ++static void ssam_hub_remove(struct ssam_device *sdev) ++{ ++ struct ssam_hub *hub = ssam_device_get_drvdata(sdev); + -+err: + ssam_device_notifier_unregister(sdev, &hub->notif); + cancel_delayed_work_sync(&hub->update_work); + ssam_remove_clients(&sdev->dev); -+ return status; +} + -+static void ssam_kip_hub_remove(struct ssam_device *sdev) ++ ++/* -- SSAM base-hub driver. ------------------------------------------------- */ ++ ++/* ++ * Some devices (especially battery) may need a bit of time to be fully usable ++ * after being (re-)connected. This delay has been determined via ++ * experimentation. ++ */ ++#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500) ++ + SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, { + .target_category = SSAM_SSH_TC_BAS, + .target_id = 0x01, +@@ -342,7 +471,7 @@ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, { + #define SSAM_BAS_OPMODE_TABLET 0x00 + #define SSAM_EVENT_BAS_CID_CONNECTION 0x0c + +-static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_hub_state *state) ++static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state) + { + u8 opmode; + int status; +@@ -354,62 +483,16 @@ static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_h + } + + if (opmode != SSAM_BAS_OPMODE_TABLET) +- *state = SSAM_BASE_HUB_CONNECTED; ++ *state = SSAM_HUB_CONNECTED; + else +- *state = SSAM_BASE_HUB_DISCONNECTED; ++ *state = SSAM_HUB_DISCONNECTED; + + return 0; + } + +-static ssize_t ssam_base_hub_state_show(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct ssam_base_hub *hub = dev_get_drvdata(dev); +- bool connected = hub->state == SSAM_BASE_HUB_CONNECTED; +- +- return sysfs_emit(buf, "%d\n", connected); +-} +- +-static struct device_attribute ssam_base_hub_attr_state = +- __ATTR(state, 0444, ssam_base_hub_state_show, NULL); +- +-static struct attribute *ssam_base_hub_attrs[] = { +- &ssam_base_hub_attr_state.attr, +- NULL, +-}; +- +-static const struct attribute_group ssam_base_hub_group = { +- .attrs = ssam_base_hub_attrs, +-}; +- +-static void ssam_base_hub_update_workfn(struct work_struct *work) +-{ +- struct ssam_base_hub *hub = container_of(work, struct ssam_base_hub, update_work.work); +- struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev); +- enum ssam_base_hub_state state; +- int status = 0; +- +- status = ssam_base_hub_query_state(hub, &state); +- if (status) +- return; +- +- if (hub->state == state) +- return; +- hub->state = state; +- +- if (hub->state == SSAM_BASE_HUB_CONNECTED) +- status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node); +- else +- ssam_remove_clients(&hub->sdev->dev); +- +- if (status) +- dev_err(&hub->sdev->dev, "failed to update base-hub devices: %d\n", status); +-} +- + static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) + { +- struct ssam_base_hub *hub = container_of(nf, struct ssam_base_hub, notif); +- unsigned long delay; ++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif); + + if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION) + return 0; +@@ -419,13 +502,7 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam + return 0; + } + +- /* +- * Delay update when the base is being connected to give devices/EC +- * some time to set up. +- */ +- delay = event->data[0] ? SSAM_BASE_UPDATE_CONNECT_DELAY : 0; +- +- schedule_delayed_work(&hub->update_work, delay); ++ ssam_hub_update(hub, event->data[0]); + + /* + * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and +@@ -435,27 +512,14 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam + return 0; + } + +-static int __maybe_unused ssam_base_hub_resume(struct device *dev) +-{ +- struct ssam_base_hub *hub = dev_get_drvdata(dev); +- +- schedule_delayed_work(&hub->update_work, 0); +- return 0; +-} +-static SIMPLE_DEV_PM_OPS(ssam_base_hub_pm_ops, NULL, ssam_base_hub_resume); +- + static int ssam_base_hub_probe(struct ssam_device *sdev) + { +- struct ssam_base_hub *hub; +- int status; ++ struct ssam_hub *hub; + + hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL); + if (!hub) + return -ENOMEM; + +- hub->sdev = sdev; +- hub->state = SSAM_BASE_HUB_UNINITIALIZED; +- + hub->notif.base.priority = INT_MAX; /* This notifier should run first. */ + hub->notif.base.fn = ssam_base_hub_notif; + hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM; +@@ -464,37 +528,10 @@ static int ssam_base_hub_probe(struct ssam_device *sdev) + hub->notif.event.mask = SSAM_EVENT_MASK_NONE; + hub->notif.event.flags = SSAM_EVENT_SEQUENCED; + +- INIT_DELAYED_WORK(&hub->update_work, ssam_base_hub_update_workfn); +- +- ssam_device_set_drvdata(sdev, hub); +- +- status = ssam_device_notifier_register(sdev, &hub->notif); +- if (status) +- return status; +- +- status = sysfs_create_group(&sdev->dev.kobj, &ssam_base_hub_group); +- if (status) +- goto err; +- +- schedule_delayed_work(&hub->update_work, 0); +- return 0; ++ hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY; ++ hub->get_state = ssam_base_hub_query_state; + +-err: +- ssam_device_notifier_unregister(sdev, &hub->notif); +- cancel_delayed_work_sync(&hub->update_work); +- ssam_remove_clients(&sdev->dev); +- return status; +-} +- +-static void ssam_base_hub_remove(struct ssam_device *sdev) +-{ +- struct ssam_base_hub *hub = ssam_device_get_drvdata(sdev); +- +- sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group); +- +- ssam_device_notifier_unregister(sdev, &hub->notif); +- cancel_delayed_work_sync(&hub->update_work); +- ssam_remove_clients(&sdev->dev); ++ return ssam_hub_setup(sdev, hub); + } + + static const struct ssam_device_id ssam_base_hub_match[] = { +@@ -504,12 +541,12 @@ static const struct ssam_device_id ssam_base_hub_match[] = { + + static struct ssam_device_driver ssam_base_hub_driver = { + .probe = ssam_base_hub_probe, +- .remove = ssam_base_hub_remove, ++ .remove = ssam_hub_remove, + .match_table = ssam_base_hub_match, + .driver = { + .name = "surface_aggregator_base_hub", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, +- .pm = &ssam_base_hub_pm_ops, ++ .pm = &ssam_hub_pm_ops, + }, + }; + +-- +2.36.1 + +From 54a66b25ae897b15bb5bb5d5f4d930f3332f7c3f Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Fri, 29 Apr 2022 23:02:06 +0200 +Subject: [PATCH] platform/surface: aggregator_registry: Add KIP device hub + +Add a Surface System Aggregator Module (SSAM) client device hub for +hot-removable devices managed via the KIP subsystem. + +The KIP subsystem (full name unknown, abbreviation has been obtained +through reverse engineering) is a subsystem that manages hot-removable +SSAM client devices. Specifically, it manages HID input devices +contained in the detachable keyboard cover of the Surface Pro 8 and +Surface Pro X. + +The KIP subsystem handles a single group of devices (e.g. all devices +contained in the keyboard cover) and cannot handle devices individually. +Thus we model it as a client device hub, which (hot-)removes all devices +contained under it once removal of the hub (e.g. keyboard cover) has +been detected and (re-)adds all devices once the physical hub device has +been (re-)attached. To do this, use the previously generified SSAM +subsystem hub framework. + +Signed-off-by: Maximilian Luz +Patchset: surface-sam +--- + .../surface/surface_aggregator_registry.c | 103 +++++++++++++++++- + 1 file changed, 101 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c +index 09cbeee2428b..1e60435c7cce 100644 +--- a/drivers/platform/surface/surface_aggregator_registry.c ++++ b/drivers/platform/surface/surface_aggregator_registry.c +@@ -551,6 +551,93 @@ static struct ssam_device_driver ssam_base_hub_driver = { + }; + + ++/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */ ++ ++/* ++ * Some devices may need a bit of time to be fully usable after being ++ * (re-)connected. This delay has been determined via experimentation. ++ */ ++#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250) ++ ++#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c ++ ++SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, { ++ .target_category = SSAM_SSH_TC_KIP, ++ .target_id = 0x01, ++ .command_id = 0x2c, ++ .instance_id = 0x00, ++}); ++ ++static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state) ++{ ++ int status; ++ u8 connected; ++ ++ status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected); ++ if (status < 0) { ++ dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status); ++ return status; ++ } ++ ++ *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED; ++ return 0; ++} ++ ++static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) +{ -+ struct ssam_kip_hub *hub = ssam_device_get_drvdata(sdev); ++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif); + -+ sysfs_remove_group(&sdev->dev.kobj, &ssam_kip_hub_group); ++ if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION) ++ return 0; /* Return "unhandled". */ + -+ ssam_device_notifier_unregister(sdev, &hub->notif); -+ cancel_delayed_work_sync(&hub->update_work); -+ ssam_remove_clients(&sdev->dev); ++ if (event->length < 1) { ++ dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length); ++ return 0; ++ } ++ ++ ssam_hub_update(hub, event->data[0]); ++ return SSAM_NOTIF_HANDLED; ++} ++ ++static int ssam_kip_hub_probe(struct ssam_device *sdev) ++{ ++ struct ssam_hub *hub; ++ ++ hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL); ++ if (!hub) ++ return -ENOMEM; ++ ++ hub->notif.base.priority = INT_MAX; /* This notifier should run first. */ ++ hub->notif.base.fn = ssam_kip_hub_notif; ++ hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM; ++ hub->notif.event.id.target_category = SSAM_SSH_TC_KIP, ++ hub->notif.event.id.instance = 0, ++ hub->notif.event.mask = SSAM_EVENT_MASK_TARGET; ++ hub->notif.event.flags = SSAM_EVENT_SEQUENCED; ++ ++ hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY; ++ hub->get_state = ssam_kip_get_connection_state; ++ ++ return ssam_hub_setup(sdev, hub); +} + +static const struct ssam_device_id ssam_kip_hub_match[] = { @@ -3588,12 +3704,12 @@ index 9f630e890ff7..4838ce6519a6 100644 + +static struct ssam_device_driver ssam_kip_hub_driver = { + .probe = ssam_kip_hub_probe, -+ .remove = ssam_kip_hub_remove, ++ .remove = ssam_hub_remove, + .match_table = ssam_kip_hub_match, + .driver = { + .name = "surface_kip_hub", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, -+ .pm = &ssam_kip_hub_pm_ops, ++ .pm = &ssam_hub_pm_ops, + }, +}; + @@ -3601,7 +3717,7 @@ index 9f630e890ff7..4838ce6519a6 100644 /* -- SSAM platform/meta-hub driver. ---------------------------------------- */ static const struct acpi_device_id ssam_platform_hub_match[] = { -@@ -636,18 +867,30 @@ static int __init ssam_device_hub_init(void) +@@ -673,18 +760,30 @@ static int __init ssam_device_hub_init(void) status = platform_driver_register(&ssam_platform_hub_driver); if (status) @@ -3635,9 +3751,9 @@ index 9f630e890ff7..4838ce6519a6 100644 platform_driver_unregister(&ssam_platform_hub_driver); } -- -2.36.0 +2.36.1 -From 0e443bc77964f90eed651cb32af45398060ba42e Mon Sep 17 00:00:00 2001 +From 6a2326ef63c3ac8b8dc45c6efee6933f649a1618 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Wed, 27 Oct 2021 22:33:03 +0200 Subject: [PATCH] platform/surface: aggregator_registry: Add support for @@ -3668,7 +3784,7 @@ Patchset: surface-sam 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c -index 4838ce6519a6..c0e29c0514df 100644 +index 1e60435c7cce..ab69669316bd 100644 --- a/drivers/platform/surface/surface_aggregator_registry.c +++ b/drivers/platform/surface/surface_aggregator_registry.c @@ -47,6 +47,12 @@ static const struct software_node ssam_node_hub_base = { @@ -3733,9 +3849,9 @@ index 4838ce6519a6..c0e29c0514df 100644 }; -- -2.36.0 +2.36.1 -From f3ff67b118c39ab15a3443f953f93fa933c1d957 Mon Sep 17 00:00:00 2001 +From 97b2239771769f3d843c72d143e7d683a7472700 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Tue, 8 Jun 2021 03:19:20 +0200 Subject: [PATCH] platform/surface: Add KIP tablet-mode switch @@ -3827,7 +3943,7 @@ index 32889482de55..6d9291c993c4 100644 obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o diff --git a/drivers/platform/surface/surface_kip_tablet_switch.c b/drivers/platform/surface/surface_kip_tablet_switch.c new file mode 100644 -index 000000000000..458470067579 +index 000000000000..27371da71ef2 --- /dev/null +++ b/drivers/platform/surface/surface_kip_tablet_switch.c @@ -0,0 +1,245 @@ @@ -3836,7 +3952,7 @@ index 000000000000..458470067579 + * Surface System Aggregator Module (SSAM) tablet mode switch via KIP + * subsystem. + * -+ * Copyright (C) 2021 Maximilian Luz ++ * Copyright (C) 2022 Maximilian Luz + */ + +#include @@ -4077,9 +4193,9 @@ index 000000000000..458470067579 +MODULE_DESCRIPTION("Tablet mode switch driver for Surface devices using KIP subsystem"); +MODULE_LICENSE("GPL"); -- -2.36.0 +2.36.1 -From 228072592809b63575ea69a4d2bb9192beb74b02 Mon Sep 17 00:00:00 2001 +From 58cb6fbb1b2613b195cdc7adfb7261888028e3c9 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Wed, 27 Oct 2021 22:33:03 +0200 Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet @@ -4097,7 +4213,7 @@ Patchset: surface-sam 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c -index c0e29c0514df..eaf0054627a5 100644 +index ab69669316bd..c666392d4a9a 100644 --- a/drivers/platform/surface/surface_aggregator_registry.c +++ b/drivers/platform/surface/surface_aggregator_registry.c @@ -77,6 +77,12 @@ static const struct software_node ssam_node_tmp_pprof = { @@ -4127,664 +4243,2258 @@ index c0e29c0514df..eaf0054627a5 100644 }; -- -2.36.0 +2.36.1 -From 82ae885ad1824b149d18d7ac938988d9a5b279d5 Mon Sep 17 00:00:00 2001 +From a330b47584598d3b8c4e80993787d7e5f1a1784e Mon Sep 17 00:00:00 2001 From: Maximilian Luz -Date: Sat, 25 Jul 2020 17:19:53 +0200 -Subject: [PATCH] i2c: acpi: Implement RawBytes read access - -Microsoft Surface Pro 4 and Book 1 devices access the MSHW0030 I2C -device via a generic serial bus operation region and RawBytes read -access. On the Surface Book 1, this access is required to turn on (and -off) the discrete GPU. - -Multiple things are to note here: - -a) The RawBytes access is device/driver dependent. The ACPI - specification states: - - > Raw accesses assume that the writer has knowledge of the bus that - > the access is made over and the device that is being accessed. The - > protocol may only ensure that the buffer is transmitted to the - > appropriate driver, but the driver must be able to interpret the - > buffer to communicate to a register. - - Thus this implementation may likely not work on other devices - accessing I2C via the RawBytes accessor type. - -b) The MSHW0030 I2C device is an HID-over-I2C device which seems to - serve multiple functions: +Date: Sat, 21 May 2022 00:30:46 +0200 +Subject: [PATCH] platform/surface: aggregator: Move device registry helper + function to core module - 1. It is the main access point for the legacy-type Surface Aggregator - Module (also referred to as SAM-over-HID, as opposed to the newer - SAM-over-SSH/UART). It has currently not been determined on how - support for the legacy SAM should be implemented. Likely via a - custom HID driver. - - 2. It seems to serve as the HID device for the Integrated Sensor Hub. - This might complicate matters with regards to implementing a - SAM-over-HID driver required by legacy SAM. - -In light of this, the simplest approach has been chosen for now. -However, it may make more sense regarding breakage and compatibility to -either provide functionality for replacing or enhancing the default -operation region handler via some additional API functions, or even to -completely blacklist MSHW0030 from the I2C core and provide a custom -driver for it. +Move helper functions for client device registration to the core module. +This simplifies addition of future DT/OF support and also allows us to +split out the device hub drivers into their own module. -Replacing/enhancing the default operation region handler would, however, -either require some sort of secondary driver and access point for it, -from which the new API functions would be called and the new handler -(part) would be installed, or hard-coding them via some sort of -quirk-like interface into the I2C core. +At the same time, also improve device node validation a bit by not +silently skipping devices with invalid device UID specifiers. Signed-off-by: Maximilian Luz -Patchset: surface-sam-over-hid +Patchset: surface-sam --- - drivers/i2c/i2c-core-acpi.c | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) + drivers/platform/surface/aggregator/bus.c | 176 ++++++++++++++++-- + .../surface/surface_aggregator_registry.c | 75 +------- + include/linux/surface_aggregator/device.h | 37 ++++ + 3 files changed, 199 insertions(+), 89 deletions(-) -diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c -index 85ed4c1d4924..942c1c9a4ea5 100644 ---- a/drivers/i2c/i2c-core-acpi.c -+++ b/drivers/i2c/i2c-core-acpi.c -@@ -624,6 +624,28 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, - return (ret == 1) ? 0 : -EIO; - } +diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c +index abbbb5b08b07..4bba60884bb5 100644 +--- a/drivers/platform/surface/aggregator/bus.c ++++ b/drivers/platform/surface/aggregator/bus.c +@@ -6,6 +6,7 @@ + */ + + #include ++#include + #include + + #include +@@ -14,6 +15,9 @@ + #include "bus.h" + #include "controller.h" -+static int acpi_gsb_i2c_write_raw_bytes(struct i2c_client *client, -+ u8 *data, u8 data_len) -+{ -+ struct i2c_msg msgs[1]; -+ int ret = AE_OK; + -+ msgs[0].addr = client->addr; -+ msgs[0].flags = client->flags; -+ msgs[0].len = data_len + 1; -+ msgs[0].buf = data; ++/* -- Device and bus functions. --------------------------------------------- */ + -+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) + { +@@ -363,6 +367,162 @@ void ssam_device_driver_unregister(struct ssam_device_driver *sdrv) + } + EXPORT_SYMBOL_GPL(ssam_device_driver_unregister); + + -+ if (ret < 0) { -+ dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret); -+ return ret; -+ } ++/* -- Bus registration. ----------------------------------------------------- */ + -+ /* 1 transfer must have completed successfully */ -+ return (ret == 1) ? 0 : -EIO; ++/** ++ * ssam_bus_register() - Register and set-up the SSAM client device bus. ++ */ ++int ssam_bus_register(void) ++{ ++ return bus_register(&ssam_bus_type); +} + - static acpi_status - i2c_acpi_space_handler(u32 function, acpi_physical_address command, - u32 bits, u64 *value64, -@@ -725,6 +747,19 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command, - } - break; - -+ case ACPI_GSB_ACCESS_ATTRIB_RAW_BYTES: -+ if (action == ACPI_READ) { -+ dev_warn(&adapter->dev, -+ "protocol 0x%02x not supported for client 0x%02x\n", -+ accessor_type, client->addr); -+ ret = AE_BAD_PARAMETER; ++/** ++ * ssam_bus_unregister() - Unregister the SSAM client device bus. ++ */ ++void ssam_bus_unregister(void) ++{ ++ return bus_unregister(&ssam_bus_type); ++} ++ ++ ++/* -- Helpers for controller and hub devices. ------------------------------- */ ++ ++static int ssam_device_uid_from_string(const char *str, struct ssam_device_uid *uid) ++{ ++ u8 d, tc, tid, iid, fn; ++ int n; ++ ++ n = sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn); ++ if (n != 5) ++ return -EINVAL; ++ ++ uid->domain = d; ++ uid->category = tc; ++ uid->target = tid; ++ uid->instance = iid; ++ uid->function = fn; ++ ++ return 0; ++} ++ ++static int ssam_get_uid_for_node(struct fwnode_handle *node, struct ssam_device_uid *uid) ++{ ++ const char* str = fwnode_get_name(node); ++ ++ /* ++ * To simplify definitions of firmware nodes, we set the device name ++ * based on the UID of the device, prefixed with "ssam:". ++ */ ++ if (strncmp(str, "ssam:", strlen("ssam:")) != 0) ++ return -ENODEV; ++ ++ str += strlen("ssam:"); ++ return ssam_device_uid_from_string(str, uid); ++} ++ ++static int ssam_add_client_device(struct device *parent, struct ssam_controller *ctrl, ++ struct fwnode_handle *node) ++{ ++ struct ssam_device_uid uid; ++ struct ssam_device *sdev; ++ int status; ++ ++ status = ssam_get_uid_for_node(node, &uid); ++ if (status) ++ return status; ++ ++ sdev = ssam_device_alloc(ctrl, uid); ++ if (!sdev) ++ return -ENOMEM; ++ ++ sdev->dev.parent = parent; ++ sdev->dev.fwnode = node; ++ ++ status = ssam_device_add(sdev); ++ if (status) ++ ssam_device_put(sdev); ++ ++ return status; ++} ++ ++/** ++ * __ssam_register_clients() - Register client devices defined under the ++ * given firmware node as children of the given device. ++ * @parent: The parent device under which clients should be registered. ++ * @ctrl: The controller with which client should be registered. ++ * @node: The firmware node holding definitions of the devices to be added. ++ * ++ * Register all clients that have been defined as children of the given root ++ * firmware node as children of the given parent device. The respective child ++ * firmware nodes will be associated with the correspondingly created child ++ * devices. ++ * ++ * The given controller will be used to instantiate the new devices. See ++ * ssam_device_add() for details. ++ * ++ * Note that, generally, the use of either ssam_device_register_clients() or ++ * ssam_register_clients() should be preferred as they directly use the ++ * firmware node and/or controller associated with the given device. This ++ * function is only intended for use when different device specifications (e.g. ++ * ACPI and firmware nodes) need to be combined (as is done in the platform hub ++ * of the device registry). ++ * ++ * Return: Returns zero on success, nonzero on failure. ++ */ ++int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl, ++ struct fwnode_handle *node) ++{ ++ struct fwnode_handle *child; ++ int status; ++ ++ fwnode_for_each_child_node(node, child) { ++ /* ++ * Try to add the device specified in the firmware node. If ++ * this fails with -ENODEV, the node does not specify any SSAM ++ * device, so ignore it and continue with the next one. ++ */ ++ status = ssam_add_client_device(parent, ctrl, child); ++ if (status && status != -ENODEV) + goto err; -+ } else { -+ status = acpi_gsb_i2c_write_raw_bytes(client, -+ gsb->data, info->access_length); -+ } -+ break; ++ } + - default: - dev_warn(&adapter->dev, "protocol 0x%02x not supported for client 0x%02x\n", - accessor_type, client->addr); ++ return 0; ++err: ++ ssam_remove_clients(parent); ++ return status; ++} ++EXPORT_SYMBOL_GPL(__ssam_register_clients); ++ ++/** ++ * ssam_register_clients() - Register all client devices defined under the ++ * given parent device. ++ * @dev: The parent device under which clients should be registered. ++ * @ctrl: The controller with which client should be registered. ++ * ++ * Register all clients that have via firmware nodes been defined as children ++ * of the given (parent) device. The respective child firmware nodes will be ++ * associated with the correspondingly created child devices. ++ * ++ * The given controller will be used to instantiate the new devices. See ++ * ssam_device_add() for details. ++ * ++ * Return: Returns zero on success, nonzero on failure. ++ */ ++int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl) ++{ ++ struct fwnode_handle *node; ++ int status; ++ ++ node = fwnode_handle_get(dev_fwnode(dev)); ++ status = __ssam_register_clients(dev, ctrl, node); ++ fwnode_handle_put(node); ++ ++ return status; ++} ++EXPORT_SYMBOL_GPL(ssam_register_clients); ++ + static int ssam_remove_device(struct device *dev, void *_data) + { + struct ssam_device *sdev = to_ssam_device(dev); +@@ -387,19 +547,3 @@ void ssam_remove_clients(struct device *dev) + device_for_each_child_reverse(dev, NULL, ssam_remove_device); + } + EXPORT_SYMBOL_GPL(ssam_remove_clients); +- +-/** +- * ssam_bus_register() - Register and set-up the SSAM client device bus. +- */ +-int ssam_bus_register(void) +-{ +- return bus_register(&ssam_bus_type); +-} +- +-/** +- * ssam_bus_unregister() - Unregister the SSAM client device bus. +- */ +-void ssam_bus_unregister(void) +-{ +- return bus_unregister(&ssam_bus_type); +-} +diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c +index c666392d4a9a..3261c8141841 100644 +--- a/drivers/platform/surface/surface_aggregator_registry.c ++++ b/drivers/platform/surface/surface_aggregator_registry.c +@@ -279,76 +279,6 @@ static const struct software_node *ssam_node_group_sp8[] = { + }; + + +-/* -- Device registry helper functions. ------------------------------------- */ +- +-static int ssam_uid_from_string(const char *str, struct ssam_device_uid *uid) +-{ +- u8 d, tc, tid, iid, fn; +- int n; +- +- n = sscanf(str, "ssam:%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn); +- if (n != 5) +- return -EINVAL; +- +- uid->domain = d; +- uid->category = tc; +- uid->target = tid; +- uid->instance = iid; +- uid->function = fn; +- +- return 0; +-} +- +-static int ssam_hub_add_device(struct device *parent, struct ssam_controller *ctrl, +- struct fwnode_handle *node) +-{ +- struct ssam_device_uid uid; +- struct ssam_device *sdev; +- int status; +- +- status = ssam_uid_from_string(fwnode_get_name(node), &uid); +- if (status) +- return status; +- +- sdev = ssam_device_alloc(ctrl, uid); +- if (!sdev) +- return -ENOMEM; +- +- sdev->dev.parent = parent; +- sdev->dev.fwnode = node; +- +- status = ssam_device_add(sdev); +- if (status) +- ssam_device_put(sdev); +- +- return status; +-} +- +-static int ssam_hub_register_clients(struct device *parent, struct ssam_controller *ctrl, +- struct fwnode_handle *node) +-{ +- struct fwnode_handle *child; +- int status; +- +- fwnode_for_each_child_node(node, child) { +- /* +- * Try to add the device specified in the firmware node. If +- * this fails with -EINVAL, the node does not specify any SSAM +- * device, so ignore it and continue with the next one. +- */ +- +- status = ssam_hub_add_device(parent, ctrl, child); +- if (status && status != -EINVAL) +- goto err; +- } +- +- return 0; +-err: +- ssam_remove_clients(parent); +- return status; +-} +- +- + /* -- SSAM generic subsystem hub driver framework. -------------------------- */ + + enum ssam_hub_state { +@@ -378,7 +308,6 @@ struct ssam_hub { + static void ssam_hub_update_workfn(struct work_struct *work) + { + struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work); +- struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev); + enum ssam_hub_state state; + int status = 0; + +@@ -418,7 +347,7 @@ static void ssam_hub_update_workfn(struct work_struct *work) + hub->state = state; + + if (hub->state == SSAM_HUB_CONNECTED) +- status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node); ++ status = ssam_device_register_clients(hub->sdev); + else + ssam_remove_clients(&hub->sdev->dev); + +@@ -762,7 +691,7 @@ static int ssam_platform_hub_probe(struct platform_device *pdev) + + set_secondary_fwnode(&pdev->dev, root); + +- status = ssam_hub_register_clients(&pdev->dev, ctrl, root); ++ status = __ssam_register_clients(&pdev->dev, ctrl, root); + if (status) { + set_secondary_fwnode(&pdev->dev, NULL); + software_node_unregister_node_group(nodes); +diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h +index ad245c6b00d0..6ae110e830b4 100644 +--- a/include/linux/surface_aggregator/device.h ++++ b/include/linux/surface_aggregator/device.h +@@ -364,11 +364,48 @@ void ssam_device_driver_unregister(struct ssam_device_driver *d); + /* -- Helpers for controller and hub devices. ------------------------------- */ + + #ifdef CONFIG_SURFACE_AGGREGATOR_BUS ++ ++int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl, ++ struct fwnode_handle *node); ++int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl); + void ssam_remove_clients(struct device *dev); ++ + #else /* CONFIG_SURFACE_AGGREGATOR_BUS */ ++ ++static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl, ++ struct fwnode_handle *node) ++{ ++ return 0; ++} ++ ++static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl) ++{ ++ return 0; ++} ++ + static inline void ssam_remove_clients(struct device *dev) {} ++ + #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */ + ++/** ++ * ssam_device_register_clients() - Register all client devices defined under ++ * the given SSAM parent device. ++ * @sdev: The parent device under which clients should be registered. ++ * ++ * Register all clients that have via firmware nodes been defined as children ++ * of the given (parent) device. The respective child firmware nodes will be ++ * associated with the correspondingly created child devices. ++ * ++ * The controller used by the parent device will be used to instantiate the new ++ * devices. See ssam_device_add() for details. ++ * ++ * Return: Returns zero on success, nonzero on failure. ++ */ ++static inline int ssam_device_register_clients(struct ssam_device *sdev) ++{ ++ return ssam_register_clients(&sdev->dev, sdev->ctrl); ++} ++ + + /* -- Helpers for client-device requests. ----------------------------------- */ + -- -2.36.0 +2.36.1 -From 704aa16555465b0f83471aa84c3a5be3c7133d67 Mon Sep 17 00:00:00 2001 +From cefc65cdcead1c23ab8a793d8a3779fed1e6f86d Mon Sep 17 00:00:00 2001 From: Maximilian Luz -Date: Sat, 13 Feb 2021 16:41:18 +0100 -Subject: [PATCH] platform/surface: Add driver for Surface Book 1 dGPU switch +Date: Sat, 21 May 2022 00:39:56 +0200 +Subject: [PATCH] platform/surface: aggregator: Move subsystem hub drivers to + their own module -Add driver exposing the discrete GPU power-switch of the Microsoft -Surface Book 1 to user-space. +Split out subsystem device hub drivers into their own module. This +allows us to load the hub drivers separately from the registry, which +will help future DT/OF support. -On the Surface Book 1, the dGPU power is controlled via the Surface -System Aggregator Module (SAM). The specific SAM-over-HID command for -this is exposed via ACPI. This module provides a simple driver exposing -the ACPI call via a sysfs parameter to user-space, so that users can -easily power-on/-off the dGPU. +While doing so, also remove a small bit of code duplication. -Patchset: surface-sam-over-hid +Signed-off-by: Maximilian Luz +Patchset: surface-sam --- - drivers/platform/surface/Kconfig | 7 + + drivers/platform/surface/Kconfig | 35 +- drivers/platform/surface/Makefile | 1 + - .../surface/surfacebook1_dgpu_switch.c | 162 ++++++++++++++++++ - 3 files changed, 170 insertions(+) - create mode 100644 drivers/platform/surface/surfacebook1_dgpu_switch.c + .../platform/surface/surface_aggregator_hub.c | 363 +++++++++++++++++ + .../surface/surface_aggregator_registry.c | 371 +----------------- + 4 files changed, 396 insertions(+), 374 deletions(-) + create mode 100644 drivers/platform/surface/surface_aggregator_hub.c diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig -index 9c228090c35b..c6c3c9bd3b57 100644 +index 9c228090c35b..c685ec440535 100644 --- a/drivers/platform/surface/Kconfig +++ b/drivers/platform/surface/Kconfig -@@ -106,6 +106,13 @@ config SURFACE_AGGREGATOR_REGISTRY - the respective client devices. Drivers for these devices still need to - be selected via the other options. +@@ -79,18 +79,45 @@ config SURFACE_AGGREGATOR_CDEV + The provided interface is intended for debugging and development only, + and should not be used otherwise. -+config SURFACE_BOOK1_DGPU_SWITCH -+ tristate "Surface Book 1 dGPU Switch Driver" -+ depends on SYSFS ++config SURFACE_AGGREGATOR_HUB ++ tristate "Surface System Aggregator Module Subsystem Device Hubs" ++ depends on SURFACE_AGGREGATOR ++ depends on SURFACE_AGGREGATOR_BUS + help -+ This driver provides a sysfs switch to set the power-state of the -+ discrete GPU found on the Microsoft Surface Book 1. -+ - config SURFACE_DTX - tristate "Surface DTX (Detachment System) Driver" ++ Device-hub drivers for Surface System Aggregator Module (SSAM) subsystem ++ devices. ++ ++ Provides subsystem hub drivers which manage client devices on various ++ SSAM subsystems. In some subsystems, notably the BAS subsystem managing ++ devices contained in the base of the Surface Book 3 and the KIP subsystem ++ managing type-cover devices in the Surface Pro 8 and Surface Pro X, ++ devices can be (hot-)removed. Hub devices and drivers are required to ++ manage these subdevices. ++ ++ Devices managed via these hubs are: ++ - Battery/AC devices (Surface Book 3). ++ - HID input devices (7th-generation and later models with detachable ++ input devices). ++ ++ Select M (recommended) or Y here if you want support for the above ++ mentioned devices on the corresponding Surface models. Without this ++ module, the respective devices mentioned above will not be instantiated ++ and thus any functionality provided by them will be missing, even when ++ drivers for these devices are present. This module only provides the ++ respective subsystem hubs. Both drivers and device specification (e.g. ++ via the Surface Aggregator Registry) for these devices still need to be ++ selected via other options. ++ + config SURFACE_AGGREGATOR_REGISTRY + tristate "Surface System Aggregator Module Device Registry" depends on SURFACE_AGGREGATOR + depends on SURFACE_AGGREGATOR_BUS + help +- Device-registry and device-hubs for Surface System Aggregator Module +- (SSAM) devices. ++ Device-registry for Surface System Aggregator Module (SSAM) devices. + + Provides a module and driver which act as a device-registry for SSAM + client devices that cannot be detected automatically, e.g. via ACPI. +- Such devices are instead provided via this registry and attached via +- device hubs, also provided in this module. ++ Such devices are instead provided and managed via this registry. + + Devices provided via this registry are: + - Platform profile (performance-/cooling-mode) device (5th- and later diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile -index 6d9291c993c4..9eb3a7e6382c 100644 +index 6d9291c993c4..fccd33e6780d 100644 --- a/drivers/platform/surface/Makefile +++ b/drivers/platform/surface/Makefile -@@ -11,6 +11,7 @@ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o +@@ -10,6 +10,7 @@ obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o + obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/ obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o ++obj-$(CONFIG_SURFACE_AGGREGATOR_HUB) += surface_aggregator_hub.o obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o -+obj-$(CONFIG_SURFACE_BOOK1_DGPU_SWITCH) += surfacebook1_dgpu_switch.o obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o - obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o -diff --git a/drivers/platform/surface/surfacebook1_dgpu_switch.c b/drivers/platform/surface/surfacebook1_dgpu_switch.c +diff --git a/drivers/platform/surface/surface_aggregator_hub.c b/drivers/platform/surface/surface_aggregator_hub.c new file mode 100644 -index 000000000000..8b816ed8f35c +index 000000000000..20b1c38debfe --- /dev/null -+++ b/drivers/platform/surface/surfacebook1_dgpu_switch.c -@@ -0,0 +1,162 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later ++++ b/drivers/platform/surface/surface_aggregator_hub.c +@@ -0,0 +1,363 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for Surface System Aggregator Module (SSAM) subsystem device hubs. ++ * ++ * Provides a driver for SSAM subsystems device hubs. This driver performs ++ * instantiation of the devices managed by said hubs and takes care of ++ * (hot-)removal. ++ * ++ * Copyright (C) 2020-2022 Maximilian Luz ++ */ + +#include ++#include +#include -+#include -+#include ++#include ++#include + ++#include + -+#ifdef pr_fmt -+#undef pr_fmt -+#endif -+#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ + ++/* -- SSAM generic subsystem hub driver framework. -------------------------- */ + -+static const guid_t dgpu_sw_guid = GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, -+ 0x95, 0xed, 0xab, 0x16, 0x65, 0x49, 0x80, 0x35); ++enum ssam_hub_state { ++ SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */ ++ SSAM_HUB_CONNECTED, ++ SSAM_HUB_DISCONNECTED, ++}; + -+#define DGPUSW_ACPI_PATH_DSM "\\_SB_.PCI0.LPCB.EC0_.VGBI" -+#define DGPUSW_ACPI_PATH_HGON "\\_SB_.PCI0.RP05.HGON" -+#define DGPUSW_ACPI_PATH_HGOF "\\_SB_.PCI0.RP05.HGOF" ++enum ssam_hub_flags { ++ SSAM_HUB_HOT_REMOVED, ++}; + ++struct ssam_hub { ++ struct ssam_device *sdev; + -+static int sb1_dgpu_sw_dsmcall(void) -+{ -+ union acpi_object *ret; -+ acpi_handle handle; -+ acpi_status status; ++ enum ssam_hub_state state; ++ unsigned long flags; + -+ status = acpi_get_handle(NULL, DGPUSW_ACPI_PATH_DSM, &handle); -+ if (status) -+ return -EINVAL; ++ struct delayed_work update_work; ++ unsigned long connect_delay; + -+ ret = acpi_evaluate_dsm_typed(handle, &dgpu_sw_guid, 1, 1, NULL, ACPI_TYPE_BUFFER); -+ if (!ret) -+ return -EINVAL; ++ struct ssam_event_notifier notif; + -+ ACPI_FREE(ret); -+ return 0; -+} ++ int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state); ++}; + -+static int sb1_dgpu_sw_hgon(void) -+{ -+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; -+ acpi_status status; ++struct ssam_hub_info { ++ struct { ++ struct ssam_event_registry reg; ++ struct ssam_event_id id; ++ enum ssam_event_mask mask; ++ u8 flags; ++ } event; + -+ status = acpi_evaluate_object(NULL, DGPUSW_ACPI_PATH_HGON, NULL, &buf); -+ if (status) { -+ pr_err("failed to run HGON: %d\n", status); -+ return -EINVAL; -+ } ++ u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event); ++ int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state); + -+ if (buf.pointer) -+ ACPI_FREE(buf.pointer); ++ unsigned long connect_delay_ms; ++}; + -+ pr_info("turned-on dGPU via HGON\n"); -+ return 0; -+} -+ -+static int sb1_dgpu_sw_hgof(void) ++static void ssam_hub_update_workfn(struct work_struct *work) +{ -+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; -+ acpi_status status; ++ struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work); ++ enum ssam_hub_state state; ++ int status = 0; + -+ status = acpi_evaluate_object(NULL, DGPUSW_ACPI_PATH_HGOF, NULL, &buf); -+ if (status) { -+ pr_err("failed to run HGOF: %d\n", status); -+ return -EINVAL; ++ status = hub->get_state(hub, &state); ++ if (status) ++ return; ++ ++ /* ++ * There is a small possibility that hub devices were hot-removed and ++ * re-added before we were able to remove them here. In that case, both ++ * the state returned by get_state() and the state of the hub will ++ * equal SSAM_HUB_CONNECTED and we would bail early below, which would ++ * leave child devices without proper (re-)initialization and the ++ * hot-remove flag set. ++ * ++ * Therefore, we check whether devices have been hot-removed via an ++ * additional flag on the hub and, in this case, override the returned ++ * hub state. In case of a missed disconnect (i.e. get_state returned ++ * "connected"), we further need to re-schedule this work (with the ++ * appropriate delay) as the actual connect work submission might have ++ * been merged with this one. ++ * ++ * This then leads to one of two cases: Either we submit an unnecessary ++ * work item (which will get ignored via either the queue or the state ++ * checks) or, in the unlikely case that the work is actually required, ++ * double the normal connect delay. ++ */ ++ if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) { ++ if (state == SSAM_HUB_CONNECTED) ++ schedule_delayed_work(&hub->update_work, hub->connect_delay); ++ ++ state = SSAM_HUB_DISCONNECTED; + } + -+ if (buf.pointer) -+ ACPI_FREE(buf.pointer); ++ if (hub->state == state) ++ return; ++ hub->state = state; ++ ++ if (hub->state == SSAM_HUB_CONNECTED) ++ status = ssam_device_register_clients(hub->sdev); ++ else ++ ssam_remove_clients(&hub->sdev->dev); ++ ++ if (status) ++ dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status); ++} ++ ++static int ssam_hub_mark_hot_removed(struct device *dev, void *_data) ++{ ++ struct ssam_device *sdev = to_ssam_device(dev); ++ ++ if (is_ssam_device(dev)) ++ ssam_device_mark_hot_removed(sdev); + -+ pr_info("turned-off dGPU via HGOF\n"); + return 0; +} + ++static void ssam_hub_update(struct ssam_hub *hub, bool connected) ++{ ++ unsigned long delay; + -+static ssize_t dgpu_dsmcall_store(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) ++ /* Mark devices as hot-removed before we remove any. */ ++ if (!connected) { ++ set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags); ++ device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed); ++ } ++ ++ /* ++ * Delay update when the base/keyboard cover is being connected to give ++ * devices/EC some time to set up. ++ */ ++ delay = connected ? hub->connect_delay : 0; ++ ++ schedule_delayed_work(&hub->update_work, delay); ++} ++ ++static int __maybe_unused ssam_hub_resume(struct device *dev) +{ -+ int status, value; ++ struct ssam_hub *hub = dev_get_drvdata(dev); + -+ status = kstrtoint(buf, 0, &value); -+ if (status < 0) -+ return status; ++ schedule_delayed_work(&hub->update_work, 0); ++ return 0; ++} ++static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume); + -+ if (value != 1) ++static int ssam_hub_probe(struct ssam_device *sdev) ++{ ++ const struct ssam_hub_info *info; ++ struct ssam_hub *hub; ++ int status; ++ ++ info = ssam_device_get_match_data(sdev); ++ if (!info) { ++ WARN(1, "no driver match data specified"); + return -EINVAL; ++ } + -+ status = sb1_dgpu_sw_dsmcall(); ++ hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL); ++ if (!hub) ++ return -ENOMEM; + -+ return status < 0 ? status : len; ++ hub->sdev = sdev; ++ hub->state = SSAM_HUB_UNINITIALIZED; ++ ++ hub->notif.base.priority = INT_MAX; /* This notifier should run first. */ ++ hub->notif.base.fn = info->notify; ++ hub->notif.event.reg = info->event.reg; ++ hub->notif.event.id = info->event.id; ++ hub->notif.event.mask = info->event.mask; ++ hub->notif.event.flags = info->event.flags; ++ ++ hub->connect_delay = msecs_to_jiffies(info->connect_delay_ms); ++ hub->get_state = info->get_state; ++ ++ INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn); ++ ++ ssam_device_set_drvdata(sdev, hub); ++ ++ status = ssam_device_notifier_register(sdev, &hub->notif); ++ if (status) ++ return status; ++ ++ schedule_delayed_work(&hub->update_work, 0); ++ return 0; +} + -+static ssize_t dgpu_power_store(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) ++static void ssam_hub_remove(struct ssam_device *sdev) +{ -+ bool power; ++ struct ssam_hub *hub = ssam_device_get_drvdata(sdev); ++ ++ ssam_device_notifier_unregister(sdev, &hub->notif); ++ cancel_delayed_work_sync(&hub->update_work); ++ ssam_remove_clients(&sdev->dev); ++} ++ ++ ++/* -- SSAM base-subsystem hub driver. --------------------------------------- */ ++ ++/* ++ * Some devices (especially battery) may need a bit of time to be fully usable ++ * after being (re-)connected. This delay has been determined via ++ * experimentation. ++ */ ++#define SSAM_BASE_UPDATE_CONNECT_DELAY 2500 ++ ++SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, { ++ .target_category = SSAM_SSH_TC_BAS, ++ .target_id = 0x01, ++ .command_id = 0x0d, ++ .instance_id = 0x00, ++}); ++ ++#define SSAM_BAS_OPMODE_TABLET 0x00 ++#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c ++ ++static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state) ++{ ++ u8 opmode; + int status; + -+ status = kstrtobool(buf, &power); -+ if (status < 0) ++ status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode); ++ if (status < 0) { ++ dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status); + return status; ++ } + -+ if (power) -+ status = sb1_dgpu_sw_hgon(); ++ if (opmode != SSAM_BAS_OPMODE_TABLET) ++ *state = SSAM_HUB_CONNECTED; + else -+ status = sb1_dgpu_sw_hgof(); ++ *state = SSAM_HUB_DISCONNECTED; + -+ return status < 0 ? status : len; ++ return 0; +} + -+static DEVICE_ATTR_WO(dgpu_dsmcall); -+static DEVICE_ATTR_WO(dgpu_power); ++static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) ++{ ++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif); + -+static struct attribute *sb1_dgpu_sw_attrs[] = { -+ &dev_attr_dgpu_dsmcall.attr, -+ &dev_attr_dgpu_power.attr, -+ NULL, -+}; ++ if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION) ++ return 0; + -+static const struct attribute_group sb1_dgpu_sw_attr_group = { -+ .attrs = sb1_dgpu_sw_attrs, ++ if (event->length < 1) { ++ dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length); ++ return 0; ++ } ++ ++ ssam_hub_update(hub, event->data[0]); ++ ++ /* ++ * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and ++ * consumed by the detachment system driver. We're just a (more or less) ++ * silent observer. ++ */ ++ return 0; ++} ++ ++static const struct ssam_hub_info base_hub = { ++ .event = { ++ .reg = SSAM_EVENT_REGISTRY_SAM, ++ .id = { ++ .target_category = SSAM_SSH_TC_BAS, ++ .instance = 0, ++ }, ++ .mask = SSAM_EVENT_MASK_NONE, ++ .flags = SSAM_EVENT_SEQUENCED, ++ }, ++ .notify = ssam_base_hub_notif, ++ .get_state = ssam_base_hub_query_state, ++ .connect_delay_ms = SSAM_BASE_UPDATE_CONNECT_DELAY, +}; + + -+static int sb1_dgpu_sw_probe(struct platform_device *pdev) ++/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */ ++ ++/* ++ * Some devices may need a bit of time to be fully usable after being ++ * (re-)connected. This delay has been determined via experimentation. ++ */ ++#define SSAM_KIP_UPDATE_CONNECT_DELAY 250 ++ ++#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c ++ ++SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_query_state, u8, { ++ .target_category = SSAM_SSH_TC_KIP, ++ .target_id = 0x01, ++ .command_id = 0x2c, ++ .instance_id = 0x00, ++}); ++ ++static int ssam_kip_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state) +{ -+ return sysfs_create_group(&pdev->dev.kobj, &sb1_dgpu_sw_attr_group); ++ int status; ++ u8 connected; ++ ++ status = ssam_retry(__ssam_kip_query_state, hub->sdev->ctrl, &connected); ++ if (status < 0) { ++ dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status); ++ return status; ++ } ++ ++ *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED; ++ return 0; +} + -+static int sb1_dgpu_sw_remove(struct platform_device *pdev) ++static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) +{ -+ sysfs_remove_group(&pdev->dev.kobj, &sb1_dgpu_sw_attr_group); -+ return 0; ++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif); ++ ++ if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION) ++ return 0; /* Return "unhandled". */ ++ ++ if (event->length < 1) { ++ dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length); ++ return 0; ++ } ++ ++ ssam_hub_update(hub, event->data[0]); ++ return SSAM_NOTIF_HANDLED; +} + -+/* -+ * The dGPU power seems to be actually handled by MSHW0040. However, that is -+ * also the power-/volume-button device with a mainline driver. So let's use -+ * MSHW0041 instead for now, which seems to be the LTCH (latch/DTX) device. -+ */ -+static const struct acpi_device_id sb1_dgpu_sw_match[] = { -+ { "MSHW0041", }, -+ { }, ++static const struct ssam_hub_info kip_hub = { ++ .event = { ++ .reg = SSAM_EVENT_REGISTRY_SAM, ++ .id = { ++ .target_category = SSAM_SSH_TC_KIP, ++ .instance = 0, ++ }, ++ .mask = SSAM_EVENT_MASK_TARGET, ++ .flags = SSAM_EVENT_SEQUENCED, ++ }, ++ .notify = ssam_kip_hub_notif, ++ .get_state = ssam_kip_hub_query_state, ++ .connect_delay_ms = SSAM_KIP_UPDATE_CONNECT_DELAY, +}; -+MODULE_DEVICE_TABLE(acpi, sb1_dgpu_sw_match); + -+static struct platform_driver sb1_dgpu_sw = { -+ .probe = sb1_dgpu_sw_probe, -+ .remove = sb1_dgpu_sw_remove, ++ ++/* -- Driver registration. -------------------------------------------------- */ ++ ++static const struct ssam_device_id ssam_hub_match[] = { ++ { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00), (unsigned long)&base_hub }, ++ { SSAM_SDEV(KIP, 0x01, 0x00, 0x00), (unsigned long)&kip_hub }, ++ { } ++}; ++MODULE_DEVICE_TABLE(ssam, ssam_hub_match); ++ ++static struct ssam_device_driver ssam_subsystem_hub_driver = { ++ .probe = ssam_hub_probe, ++ .remove = ssam_hub_remove, ++ .match_table = ssam_hub_match, + .driver = { -+ .name = "surfacebook1_dgpu_switch", -+ .acpi_match_table = sb1_dgpu_sw_match, ++ .name = "surface_aggregator_subsystem_hub", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, ++ .pm = &ssam_hub_pm_ops, + }, +}; -+module_platform_driver(sb1_dgpu_sw); ++module_ssam_device_driver(ssam_subsystem_hub_driver); + +MODULE_AUTHOR("Maximilian Luz "); -+MODULE_DESCRIPTION("Discrete GPU Power-Switch for Surface Book 1"); ++MODULE_DESCRIPTION("Subsystem device hub driver for Surface System Aggregator Module"); +MODULE_LICENSE("GPL"); --- -2.36.0 - -From 5a6d26ae3ff1334f0540aef76b28c596ebb67d81 Mon Sep 17 00:00:00 2001 -From: Maximilian Luz -Date: Wed, 27 Oct 2021 00:56:11 +0200 -Subject: [PATCH] platform/surface: gpe: Add support for Surface Pro 8 - -The new Surface Pro 8 uses GPEs for lid events as well. Add an entry for -that so that the lid can be used to wake the device. Note that this is a -device with a keyboard type cover, where this acts as the "lid". - -Signed-off-by: Maximilian Luz -Patchset: surface-gpe ---- - drivers/platform/surface/surface_gpe.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c -index c1775db29efb..ec66fde28e75 100644 ---- a/drivers/platform/surface/surface_gpe.c -+++ b/drivers/platform/surface/surface_gpe.c -@@ -99,6 +99,14 @@ static const struct dmi_system_id dmi_lid_device_table[] = { - }, - .driver_data = (void *)lid_device_props_l4D, - }, -+ { -+ .ident = "Surface Pro 8", -+ .matches = { -+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 8"), -+ }, -+ .driver_data = (void *)lid_device_props_l4B, -+ }, - { - .ident = "Surface Book 1", - .matches = { --- -2.36.0 - -From 8944aec8973646c474c14bd6763adee38f0430a3 Mon Sep 17 00:00:00 2001 -From: Sachi King -Date: Tue, 5 Oct 2021 00:05:09 +1100 -Subject: [PATCH] Input: soc_button_array - support AMD variant Surface devices - -The power button on the AMD variant of the Surface Laptop uses the -same MSHW0040 device ID as the 5th and later generation of Surface -devices, however they report 0 for their OEM platform revision. As the -_DSM does not exist on the devices requiring special casing, check for -the existance of the _DSM to determine if soc_button_array should be -loaded. - -Fixes: c394159310d0 ("Input: soc_button_array - add support for newer surface devices") -Co-developed-by: Maximilian Luz - -Signed-off-by: Sachi King -Patchset: surface-button ---- - drivers/input/misc/soc_button_array.c | 33 +++++++-------------------- - 1 file changed, 8 insertions(+), 25 deletions(-) - -diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c -index cb6ec59a045d..4e8944f59def 100644 ---- a/drivers/input/misc/soc_button_array.c -+++ b/drivers/input/misc/soc_button_array.c -@@ -474,8 +474,8 @@ static const struct soc_device_data soc_device_INT33D3 = { - * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned - * devices use MSHW0040 for power and volume buttons, however the way they - * have to be addressed differs. Make sure that we only load this drivers -- * for the correct devices by checking the OEM Platform Revision provided by -- * the _DSM method. -+ * for the correct devices by checking if the OEM Platform Revision DSM call -+ * exists. - */ - #define MSHW0040_DSM_REVISION 0x01 - #define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision -@@ -486,31 +486,14 @@ static const guid_t MSHW0040_DSM_UUID = - static int soc_device_check_MSHW0040(struct device *dev) - { - acpi_handle handle = ACPI_HANDLE(dev); -- union acpi_object *result; -- u64 oem_platform_rev = 0; // valid revisions are nonzero +diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c +index 3261c8141841..11b51aa9ea73 100644 +--- a/drivers/platform/surface/surface_aggregator_registry.c ++++ b/drivers/platform/surface/surface_aggregator_registry.c +@@ -11,14 +11,11 @@ + + #include + #include +-#include + #include + #include + #include + #include +-#include + +-#include + #include + + +@@ -279,335 +276,6 @@ static const struct software_node *ssam_node_group_sp8[] = { + }; + + +-/* -- SSAM generic subsystem hub driver framework. -------------------------- */ - -- // get OEM platform revision -- result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID, -- MSHW0040_DSM_REVISION, -- MSHW0040_DSM_GET_OMPR, NULL, -- ACPI_TYPE_INTEGER); +-enum ssam_hub_state { +- SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */ +- SSAM_HUB_CONNECTED, +- SSAM_HUB_DISCONNECTED, +-}; - -- if (result) { -- oem_platform_rev = result->integer.value; -- ACPI_FREE(result); +-enum ssam_hub_flags { +- SSAM_HUB_HOT_REMOVED, +-}; +- +-struct ssam_hub { +- struct ssam_device *sdev; +- +- enum ssam_hub_state state; +- unsigned long flags; +- +- struct delayed_work update_work; +- unsigned long connect_delay; +- +- struct ssam_event_notifier notif; +- +- int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state); +-}; +- +-static void ssam_hub_update_workfn(struct work_struct *work) +-{ +- struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work); +- enum ssam_hub_state state; +- int status = 0; +- +- status = hub->get_state(hub, &state); +- if (status) +- return; +- +- /* +- * There is a small possibility that hub devices were hot-removed and +- * re-added before we were able to remove them here. In that case, both +- * the state returned by get_state() and the state of the hub will +- * equal SSAM_HUB_CONNECTED and we would bail early below, which would +- * leave child devices without proper (re-)initialization and the +- * hot-remove flag set. +- * +- * Therefore, we check whether devices have been hot-removed via an +- * additional flag on the hub and, in this case, override the returned +- * hub state. In case of a missed disconnect (i.e. get_state returned +- * "connected"), we further need to re-schedule this work (with the +- * appropriate delay) as the actual connect work submission might have +- * been merged with this one. +- * +- * This then leads to one of two cases: Either we submit an unnecessary +- * work item (which will get ignored via either the queue or the state +- * checks) or, in the unlikely case that the work is actually required, +- * double the normal connect delay. +- */ +- if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) { +- if (state == SSAM_HUB_CONNECTED) +- schedule_delayed_work(&hub->update_work, hub->connect_delay); +- +- state = SSAM_HUB_DISCONNECTED; +- } +- +- if (hub->state == state) +- return; +- hub->state = state; +- +- if (hub->state == SSAM_HUB_CONNECTED) +- status = ssam_device_register_clients(hub->sdev); +- else +- ssam_remove_clients(&hub->sdev->dev); +- +- if (status) +- dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status); +-} +- +-static int ssam_hub_mark_hot_removed(struct device *dev, void *_data) +-{ +- struct ssam_device *sdev = to_ssam_device(dev); +- +- if (is_ssam_device(dev)) +- ssam_device_mark_hot_removed(sdev); +- +- return 0; +-} +- +-static void ssam_hub_update(struct ssam_hub *hub, bool connected) +-{ +- unsigned long delay; +- +- /* Mark devices as hot-removed before we remove any. */ +- if (!connected) { +- set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags); +- device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed); - } - - /* -- * If the revision is zero here, the _DSM evaluation has failed. This -- * indicates that we have a Pro 4 or Book 1 and this driver should not -- * be used. +- * Delay update when the base/keyboard cover is being connected to give +- * devices/EC some time to set up. - */ -- if (oem_platform_rev == 0) -- return -ENODEV; -+ bool exists; - -- dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev); -+ // check if OEM platform revision DSM call exists -+ exists = acpi_check_dsm(handle, &MSHW0040_DSM_UUID, -+ MSHW0040_DSM_REVISION, -+ BIT(MSHW0040_DSM_GET_OMPR)); - +- delay = connected ? hub->connect_delay : 0; +- +- schedule_delayed_work(&hub->update_work, delay); +-} +- +-static int __maybe_unused ssam_hub_resume(struct device *dev) +-{ +- struct ssam_hub *hub = dev_get_drvdata(dev); +- +- schedule_delayed_work(&hub->update_work, 0); - return 0; -+ return exists ? 0 : -ENODEV; - } - - /* --- -2.36.0 - -From 421af81b0297af32e058cd79dcf3073eb3cf51fa Mon Sep 17 00:00:00 2001 -From: Sachi King -Date: Tue, 5 Oct 2021 00:22:57 +1100 -Subject: [PATCH] platform/surface: surfacepro3_button: don't load on amd - variant - -The AMD variant of the Surface Laptop report 0 for their OEM platform -revision. The Surface devices that require the surfacepro3_button -driver do not have the _DSM that gets the OEM platform revision. If the -method does not exist, load surfacepro3_button. - -Fixes: 64dd243d7356 ("platform/x86: surfacepro3_button: Fix device check") -Co-developed-by: Maximilian Luz - -Signed-off-by: Sachi King -Patchset: surface-button ---- - drivers/platform/surface/surfacepro3_button.c | 30 ++++--------------- - 1 file changed, 6 insertions(+), 24 deletions(-) - -diff --git a/drivers/platform/surface/surfacepro3_button.c b/drivers/platform/surface/surfacepro3_button.c -index 242fb690dcaf..30eea54dbb47 100644 ---- a/drivers/platform/surface/surfacepro3_button.c -+++ b/drivers/platform/surface/surfacepro3_button.c -@@ -149,7 +149,8 @@ static int surface_button_resume(struct device *dev) - /* - * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device - * ID (MSHW0040) for the power/volume buttons. Make sure this is the right -- * device by checking for the _DSM method and OEM Platform Revision. -+ * device by checking for the _DSM method and OEM Platform Revision DSM -+ * function. - * - * Returns true if the driver should bind to this device, i.e. the device is - * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1. -@@ -157,30 +158,11 @@ static int surface_button_resume(struct device *dev) - static bool surface_button_check_MSHW0040(struct acpi_device *dev) - { - acpi_handle handle = dev->handle; -- union acpi_object *result; -- u64 oem_platform_rev = 0; // valid revisions are nonzero +-} +-static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume); - -- // get OEM platform revision -- result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID, -- MSHW0040_DSM_REVISION, -- MSHW0040_DSM_GET_OMPR, -- NULL, ACPI_TYPE_INTEGER); +-static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub) +-{ +- int status; +- +- hub->sdev = sdev; +- hub->state = SSAM_HUB_UNINITIALIZED; +- +- INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn); +- +- ssam_device_set_drvdata(sdev, hub); +- +- status = ssam_device_notifier_register(sdev, &hub->notif); +- if (status) +- return status; +- +- schedule_delayed_work(&hub->update_work, 0); +- return 0; +-} +- +-static void ssam_hub_remove(struct ssam_device *sdev) +-{ +- struct ssam_hub *hub = ssam_device_get_drvdata(sdev); +- +- ssam_device_notifier_unregister(sdev, &hub->notif); +- cancel_delayed_work_sync(&hub->update_work); +- ssam_remove_clients(&sdev->dev); +-} +- +- +-/* -- SSAM base-hub driver. ------------------------------------------------- */ +- +-/* +- * Some devices (especially battery) may need a bit of time to be fully usable +- * after being (re-)connected. This delay has been determined via +- * experimentation. +- */ +-#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500) +- +-SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, { +- .target_category = SSAM_SSH_TC_BAS, +- .target_id = 0x01, +- .command_id = 0x0d, +- .instance_id = 0x00, +-}); +- +-#define SSAM_BAS_OPMODE_TABLET 0x00 +-#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c +- +-static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state) +-{ +- u8 opmode; +- int status; +- +- status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode); +- if (status < 0) { +- dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status); +- return status; +- } +- +- if (opmode != SSAM_BAS_OPMODE_TABLET) +- *state = SSAM_HUB_CONNECTED; +- else +- *state = SSAM_HUB_DISCONNECTED; +- +- return 0; +-} +- +-static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) +-{ +- struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif); +- +- if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION) +- return 0; +- +- if (event->length < 1) { +- dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length); +- return 0; +- } +- +- ssam_hub_update(hub, event->data[0]); - - /* -- * If evaluating the _DSM fails, the method is not present. This means -- * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we -- * should use this driver. We use revision 0 indicating it is -- * unavailable. +- * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and +- * consumed by the detachment system driver. We're just a (more or less) +- * silent observer. - */ +- return 0; +-} - -- if (result) { -- oem_platform_rev = result->integer.value; -- ACPI_FREE(result); +-static int ssam_base_hub_probe(struct ssam_device *sdev) +-{ +- struct ssam_hub *hub; +- +- hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL); +- if (!hub) +- return -ENOMEM; +- +- hub->notif.base.priority = INT_MAX; /* This notifier should run first. */ +- hub->notif.base.fn = ssam_base_hub_notif; +- hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM; +- hub->notif.event.id.target_category = SSAM_SSH_TC_BAS, +- hub->notif.event.id.instance = 0, +- hub->notif.event.mask = SSAM_EVENT_MASK_NONE; +- hub->notif.event.flags = SSAM_EVENT_SEQUENCED; +- +- hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY; +- hub->get_state = ssam_base_hub_query_state; +- +- return ssam_hub_setup(sdev, hub); +-} +- +-static const struct ssam_device_id ssam_base_hub_match[] = { +- { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00) }, +- { }, +-}; +- +-static struct ssam_device_driver ssam_base_hub_driver = { +- .probe = ssam_base_hub_probe, +- .remove = ssam_hub_remove, +- .match_table = ssam_base_hub_match, +- .driver = { +- .name = "surface_aggregator_base_hub", +- .probe_type = PROBE_PREFER_ASYNCHRONOUS, +- .pm = &ssam_hub_pm_ops, +- }, +-}; +- +- +-/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */ +- +-/* +- * Some devices may need a bit of time to be fully usable after being +- * (re-)connected. This delay has been determined via experimentation. +- */ +-#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250) +- +-#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c +- +-SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, { +- .target_category = SSAM_SSH_TC_KIP, +- .target_id = 0x01, +- .command_id = 0x2c, +- .instance_id = 0x00, +-}); +- +-static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state) +-{ +- int status; +- u8 connected; +- +- status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected); +- if (status < 0) { +- dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status); +- return status; - } - -- dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev); - -- return oem_platform_rev == 0; -+ // make sure that OEM platform revision DSM call does not exist -+ return !acpi_check_dsm(handle, &MSHW0040_DSM_UUID, -+ MSHW0040_DSM_REVISION, -+ BIT(MSHW0040_DSM_GET_OMPR)); - } +- *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED; +- return 0; +-} +- +-static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event) +-{ +- struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif); +- +- if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION) +- return 0; /* Return "unhandled". */ +- +- if (event->length < 1) { +- dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length); +- return 0; +- } +- +- ssam_hub_update(hub, event->data[0]); +- return SSAM_NOTIF_HANDLED; +-} +- +-static int ssam_kip_hub_probe(struct ssam_device *sdev) +-{ +- struct ssam_hub *hub; +- +- hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL); +- if (!hub) +- return -ENOMEM; +- +- hub->notif.base.priority = INT_MAX; /* This notifier should run first. */ +- hub->notif.base.fn = ssam_kip_hub_notif; +- hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM; +- hub->notif.event.id.target_category = SSAM_SSH_TC_KIP, +- hub->notif.event.id.instance = 0, +- hub->notif.event.mask = SSAM_EVENT_MASK_TARGET; +- hub->notif.event.flags = SSAM_EVENT_SEQUENCED; +- +- hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY; +- hub->get_state = ssam_kip_get_connection_state; +- +- return ssam_hub_setup(sdev, hub); +-} +- +-static const struct ssam_device_id ssam_kip_hub_match[] = { +- { SSAM_SDEV(KIP, 0x01, 0x00, 0x00) }, +- { }, +-}; +- +-static struct ssam_device_driver ssam_kip_hub_driver = { +- .probe = ssam_kip_hub_probe, +- .remove = ssam_hub_remove, +- .match_table = ssam_kip_hub_match, +- .driver = { +- .name = "surface_kip_hub", +- .probe_type = PROBE_PREFER_ASYNCHRONOUS, +- .pm = &ssam_hub_pm_ops, +- }, +-}; +- +- + /* -- SSAM platform/meta-hub driver. ---------------------------------------- */ + static const struct acpi_device_id ssam_platform_hub_match[] = { +@@ -720,44 +388,7 @@ static struct platform_driver ssam_platform_hub_driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + }; +- +- +-/* -- Module initialization. ------------------------------------------------ */ +- +-static int __init ssam_device_hub_init(void) +-{ +- int status; +- +- status = platform_driver_register(&ssam_platform_hub_driver); +- if (status) +- goto err_platform; +- +- status = ssam_device_driver_register(&ssam_base_hub_driver); +- if (status) +- goto err_base; +- +- status = ssam_device_driver_register(&ssam_kip_hub_driver); +- if (status) +- goto err_kip; +- +- return 0; +- +-err_kip: +- ssam_device_driver_unregister(&ssam_base_hub_driver); +-err_base: +- platform_driver_unregister(&ssam_platform_hub_driver); +-err_platform: +- return status; +-} +-module_init(ssam_device_hub_init); +- +-static void __exit ssam_device_hub_exit(void) +-{ +- ssam_device_driver_unregister(&ssam_kip_hub_driver); +- ssam_device_driver_unregister(&ssam_base_hub_driver); +- platform_driver_unregister(&ssam_platform_hub_driver); +-} +-module_exit(ssam_device_hub_exit); ++module_platform_driver(ssam_platform_hub_driver); + MODULE_AUTHOR("Maximilian Luz "); + MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module"); -- -2.36.0 - -From 734da7d8f5beb9be996ba99a80f7e603b72130ab Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 24 Feb 2022 12:02:40 +0100 -Subject: [PATCH] Input: soc_button_array - add support for Microsoft Surface 3 - (MSHW0028) buttons - -The drivers/platform/surface/surface3_button.c code is alsmost a 1:1 copy -of the soc_button_array code. +2.36.1 -The only big difference is that it binds to an i2c_client rather then to -a platform_device. The cause of this is the ACPI resources for the MSHW0028 -device containing a bogus I2cSerialBusV2 resource which causes the kernel -to instantiate an i2c_client for it instead of a platform_device. +From e2d2b665e1877096405e8c6b84922880d4bb795b Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Sat, 21 May 2022 00:51:05 +0200 +Subject: [PATCH] platform/surface: aggregator: Be consistent with hub device + IDs -Add "MSHW0028" to the ignore_serial_bus_ids[] list in drivers/apci/scan.c, -so that a platform_device will be instantiated and add support for -the MSHW0028 HID to soc_button_array. +Currently, we use a virtual device ID for the base (BAS) hub but an +actual device ID for the KIP hub. Let's be consistent about the naming +format and make all hubs virtual, with their instance ID reflecting the +subsystem. -This fully replaces surface3_button, which will be removed in a separate -commit (since it binds to the now no longer created i2c_client it no -longer does anyyhing after this commit). - -Note the MSHW0028 id is used by Microsoft to describe the tablet buttons on -both the Surface 3 and the Surface 3 Pro and the actual API/implementation -for the Surface 3 Pro is quite different. The changes in this commit should -not impact the separate surfacepro3_button driver: +Signed-off-by: Maximilian Luz +Patchset: surface-sam +--- + drivers/platform/surface/surface_aggregator_hub.c | 4 ++-- + .../platform/surface/surface_aggregator_registry.c | 12 ++++++------ + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/platform/surface/surface_aggregator_hub.c b/drivers/platform/surface/surface_aggregator_hub.c +index 20b1c38debfe..c473bdebf90c 100644 +--- a/drivers/platform/surface/surface_aggregator_hub.c ++++ b/drivers/platform/surface/surface_aggregator_hub.c +@@ -340,8 +340,8 @@ static const struct ssam_hub_info kip_hub = { + /* -- Driver registration. -------------------------------------------------- */ + + static const struct ssam_device_id ssam_hub_match[] = { +- { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00), (unsigned long)&base_hub }, +- { SSAM_SDEV(KIP, 0x01, 0x00, 0x00), (unsigned long)&kip_hub }, ++ { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00), (unsigned long)&kip_hub }, ++ { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00), (unsigned long)&base_hub }, + { } + }; + MODULE_DEVICE_TABLE(ssam, ssam_hub_match); +diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c +index 11b51aa9ea73..cee7121e7fa6 100644 +--- a/drivers/platform/surface/surface_aggregator_registry.c ++++ b/drivers/platform/surface/surface_aggregator_registry.c +@@ -38,15 +38,15 @@ static const struct software_node ssam_node_root = { + .name = "ssam_platform_hub", + }; + +-/* Base device hub (devices attached to Surface Book 3 base). */ +-static const struct software_node ssam_node_hub_base = { +- .name = "ssam:00:00:02:00:00", ++/* KIP device hub (connects keyboard cover devices on Surface Pro 8). */ ++static const struct software_node ssam_node_hub_kip = { ++ .name = "ssam:00:00:01:0e:00", + .parent = &ssam_node_root, + }; + +-/* KIP device hub (connects keyboard cover devices on Surface Pro 8). */ +-static const struct software_node ssam_node_hub_kip = { +- .name = "ssam:01:0e:01:00:00", ++/* Base device hub (devices attached to Surface Book 3 base). */ ++static const struct software_node ssam_node_hub_base = { ++ .name = "ssam:00:00:02:11:00", + .parent = &ssam_node_root, + }; + +-- +2.36.1 -1. Because of the bogus I2cSerialBusV2 resource problem that driver binds - to the acpi_device itself, so instantiating a platform_device instead of - an i2c_client does not matter. +From 525b0a215a224a430766886ae4f382f5684095f2 Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Sat, 21 May 2022 00:57:40 +0200 +Subject: [PATCH] platform/surface: Update copyright year of various drivers -2. The soc_button_array driver will not bind to the MSHW0028 device on - the Surface 3 Pro, because it has no GPIO resources. +Update the copyright of various Surface drivers to the current year. -Signed-off-by: Hans de Goede -Reviewed-by: Maximilian Luz +Patchset: surface-sam --- - drivers/acpi/scan.c | 5 +++++ - drivers/input/misc/soc_button_array.c | 24 +++++++++++++++++++++++- - 2 files changed, 28 insertions(+), 1 deletion(-) - -diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c -index 8b2e5ef15559..c82b1bfa1c3d 100644 ---- a/drivers/acpi/scan.c -+++ b/drivers/acpi/scan.c -@@ -1753,6 +1753,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) - */ - {"BCM4752", }, - {"LNV4752", }, -+ /* -+ * Some ACPI devs contain SerialBus resources even though they are not -+ * attached to a serial bus at all. -+ */ -+ {"MSHW0028", }, - {} - }; + drivers/platform/surface/aggregator/Kconfig | 2 +- + drivers/platform/surface/aggregator/Makefile | 2 +- + drivers/platform/surface/aggregator/bus.c | 2 +- + drivers/platform/surface/aggregator/bus.h | 2 +- + drivers/platform/surface/aggregator/controller.c | 2 +- + drivers/platform/surface/aggregator/controller.h | 2 +- + drivers/platform/surface/aggregator/core.c | 2 +- + drivers/platform/surface/aggregator/ssh_msgb.h | 2 +- + drivers/platform/surface/aggregator/ssh_packet_layer.c | 2 +- + drivers/platform/surface/aggregator/ssh_packet_layer.h | 2 +- + drivers/platform/surface/aggregator/ssh_parser.c | 2 +- + drivers/platform/surface/aggregator/ssh_parser.h | 2 +- + drivers/platform/surface/aggregator/ssh_request_layer.c | 2 +- + drivers/platform/surface/aggregator/ssh_request_layer.h | 2 +- + drivers/platform/surface/aggregator/trace.h | 2 +- + drivers/platform/surface/surface_acpi_notify.c | 2 +- + drivers/platform/surface/surface_aggregator_cdev.c | 2 +- + drivers/platform/surface/surface_aggregator_registry.c | 2 +- + drivers/platform/surface/surface_dtx.c | 2 +- + drivers/platform/surface/surface_gpe.c | 2 +- + drivers/platform/surface/surface_hotplug.c | 2 +- + drivers/platform/surface/surface_platform_profile.c | 2 +- + 22 files changed, 22 insertions(+), 22 deletions(-) + +diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig +index cab020324256..c114f9dd5fe1 100644 +--- a/drivers/platform/surface/aggregator/Kconfig ++++ b/drivers/platform/surface/aggregator/Kconfig +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0+ +-# Copyright (C) 2019-2021 Maximilian Luz ++# Copyright (C) 2019-2022 Maximilian Luz + + menuconfig SURFACE_AGGREGATOR + tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers" +diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile +index c0d550eda5cd..fdf664a217f9 100644 +--- a/drivers/platform/surface/aggregator/Makefile ++++ b/drivers/platform/surface/aggregator/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0+ +-# Copyright (C) 2019-2021 Maximilian Luz ++# Copyright (C) 2019-2022 Maximilian Luz + + # For include/trace/define_trace.h to include trace.h + CFLAGS_core.o = -I$(src) +diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c +index 4bba60884bb5..96986042a257 100644 +--- a/drivers/platform/surface/aggregator/bus.c ++++ b/drivers/platform/surface/aggregator/bus.c +@@ -2,7 +2,7 @@ + /* + * Surface System Aggregator Module bus and device integration. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ -diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c -index 4e8944f59def..f044c731c6a9 100644 ---- a/drivers/input/misc/soc_button_array.c -+++ b/drivers/input/misc/soc_button_array.c -@@ -469,6 +469,27 @@ static const struct soc_device_data soc_device_INT33D3 = { - .button_info = soc_button_INT33D3, - }; + #include +diff --git a/drivers/platform/surface/aggregator/bus.h b/drivers/platform/surface/aggregator/bus.h +index 6964ee84e79c..5b4dbf21906c 100644 +--- a/drivers/platform/surface/aggregator/bus.h ++++ b/drivers/platform/surface/aggregator/bus.h +@@ -2,7 +2,7 @@ + /* + * Surface System Aggregator Module bus and device integration. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ -+/* -+ * Button info for Microsoft Surface 3 (non pro), this is indentical to -+ * the PNP0C40 info except that the home button is active-high. -+ * -+ * The Surface 3 Pro also has a MSHW0028 ACPI device, but that uses a custom -+ * version of the drivers/platform/x86/intel/hid.c 5 button array ACPI API -+ * instead. A check() callback is not necessary though as the Surface 3 Pro -+ * MSHW0028 ACPI device's resource table does not contain any GPIOs. -+ */ -+static const struct soc_button_info soc_button_MSHW0028[] = { -+ { "power", 0, EV_KEY, KEY_POWER, false, true, true }, -+ { "home", 1, EV_KEY, KEY_LEFTMETA, false, true, false }, -+ { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true }, -+ { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true }, -+ { } -+}; -+ -+static const struct soc_device_data soc_device_MSHW0028 = { -+ .button_info = soc_button_MSHW0028, -+}; -+ + #ifndef _SURFACE_AGGREGATOR_BUS_H +diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c +index 6de834b52b63..43e765199137 100644 +--- a/drivers/platform/surface/aggregator/controller.c ++++ b/drivers/platform/surface/aggregator/controller.c +@@ -2,7 +2,7 @@ /* - * Special device check for Surface Book 2 and Surface Pro (2017). - * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned -@@ -518,7 +539,8 @@ static const struct acpi_device_id soc_button_acpi_match[] = { - { "ID9001", (unsigned long)&soc_device_INT33D3 }, - { "ACPI0011", 0 }, + * Main SSAM/SSH controller structure and functionality. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ -- /* Microsoft Surface Devices (5th and 6th generation) */ -+ /* Microsoft Surface Devices (3th, 5th and 6th generation) */ -+ { "MSHW0028", (unsigned long)&soc_device_MSHW0028 }, - { "MSHW0040", (unsigned long)&soc_device_MSHW0040 }, + #include +diff --git a/drivers/platform/surface/aggregator/controller.h b/drivers/platform/surface/aggregator/controller.h +index a0963c3562ff..f0d987abc51e 100644 +--- a/drivers/platform/surface/aggregator/controller.h ++++ b/drivers/platform/surface/aggregator/controller.h +@@ -2,7 +2,7 @@ + /* + * Main SSAM/SSH controller structure and functionality. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ - { } + #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H +diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c +index a62c5dfe42d6..1a6373dea109 100644 +--- a/drivers/platform/surface/aggregator/core.c ++++ b/drivers/platform/surface/aggregator/core.c +@@ -7,7 +7,7 @@ + * Handles communication via requests as well as enabling, disabling, and + * relaying of events. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/aggregator/ssh_msgb.h b/drivers/platform/surface/aggregator/ssh_msgb.h +index e562958ffdf0..f3ecad92eefd 100644 +--- a/drivers/platform/surface/aggregator/ssh_msgb.h ++++ b/drivers/platform/surface/aggregator/ssh_msgb.h +@@ -2,7 +2,7 @@ + /* + * SSH message builder functions. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H +diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c +index 8a4451c1ffe5..6748fe4ac5d5 100644 +--- a/drivers/platform/surface/aggregator/ssh_packet_layer.c ++++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c +@@ -2,7 +2,7 @@ + /* + * SSH packet transport layer. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.h b/drivers/platform/surface/aggregator/ssh_packet_layer.h +index 2eb329f0b91a..64633522f971 100644 +--- a/drivers/platform/surface/aggregator/ssh_packet_layer.h ++++ b/drivers/platform/surface/aggregator/ssh_packet_layer.h +@@ -2,7 +2,7 @@ + /* + * SSH packet transport layer. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H +diff --git a/drivers/platform/surface/aggregator/ssh_parser.c b/drivers/platform/surface/aggregator/ssh_parser.c +index b77912f8f13b..a6f668694365 100644 +--- a/drivers/platform/surface/aggregator/ssh_parser.c ++++ b/drivers/platform/surface/aggregator/ssh_parser.c +@@ -2,7 +2,7 @@ + /* + * SSH message parser. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/aggregator/ssh_parser.h b/drivers/platform/surface/aggregator/ssh_parser.h +index 3bd6e180fd16..801d8fa69fb5 100644 +--- a/drivers/platform/surface/aggregator/ssh_parser.h ++++ b/drivers/platform/surface/aggregator/ssh_parser.h +@@ -2,7 +2,7 @@ + /* + * SSH message parser. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H +diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c +index 790f7f0eee98..f5565570f16c 100644 +--- a/drivers/platform/surface/aggregator/ssh_request_layer.c ++++ b/drivers/platform/surface/aggregator/ssh_request_layer.c +@@ -2,7 +2,7 @@ + /* + * SSH request transport layer. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.h b/drivers/platform/surface/aggregator/ssh_request_layer.h +index 9c3cbae2d4bd..4e387a031351 100644 +--- a/drivers/platform/surface/aggregator/ssh_request_layer.h ++++ b/drivers/platform/surface/aggregator/ssh_request_layer.h +@@ -2,7 +2,7 @@ + /* + * SSH request transport layer. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H +diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h +index de64cf169060..7be0bb097dea 100644 +--- a/drivers/platform/surface/aggregator/trace.h ++++ b/drivers/platform/surface/aggregator/trace.h +@@ -2,7 +2,7 @@ + /* + * Trace points for SSAM/SSH. + * +- * Copyright (C) 2020-2021 Maximilian Luz ++ * Copyright (C) 2020-2022 Maximilian Luz + */ + + #undef TRACE_SYSTEM +diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c +index 8339988d95c1..acc958b43b57 100644 +--- a/drivers/platform/surface/surface_acpi_notify.c ++++ b/drivers/platform/surface/surface_acpi_notify.c +@@ -8,7 +8,7 @@ + * notifications sent from ACPI via the SAN interface by providing them to any + * registered external driver. + * +- * Copyright (C) 2019-2020 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c +index 30fb50fde450..492c82e69182 100644 +--- a/drivers/platform/surface/surface_aggregator_cdev.c ++++ b/drivers/platform/surface/surface_aggregator_cdev.c +@@ -3,7 +3,7 @@ + * Provides user-space access to the SSAM EC via the /dev/surface/aggregator + * misc device. Intended for debugging and development. + * +- * Copyright (C) 2020-2021 Maximilian Luz ++ * Copyright (C) 2020-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c +index cee7121e7fa6..3f81db28a702 100644 +--- a/drivers/platform/surface/surface_aggregator_registry.c ++++ b/drivers/platform/surface/surface_aggregator_registry.c +@@ -6,7 +6,7 @@ + * cannot be auto-detected. Provides device-hubs and performs instantiation + * for these devices. + * +- * Copyright (C) 2020-2021 Maximilian Luz ++ * Copyright (C) 2020-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/surface_dtx.c b/drivers/platform/surface/surface_dtx.c +index 1203b9a82993..ed36944467f9 100644 +--- a/drivers/platform/surface/surface_dtx.c ++++ b/drivers/platform/surface/surface_dtx.c +@@ -8,7 +8,7 @@ + * acknowledge (to speed things up), abort (e.g. in case the dGPU is still in + * use), or request detachment via user-space. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c +index c1775db29efb..b7e48ba100b6 100644 +--- a/drivers/platform/surface/surface_gpe.c ++++ b/drivers/platform/surface/surface_gpe.c +@@ -4,7 +4,7 @@ + * properly configuring the respective GPEs. Required for wakeup via lid on + * newer Intel-based Microsoft Surface devices. + * +- * Copyright (C) 2020 Maximilian Luz ++ * Copyright (C) 2020-2022 Maximilian Luz + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +diff --git a/drivers/platform/surface/surface_hotplug.c b/drivers/platform/surface/surface_hotplug.c +index cfcc15cfbacb..f004a2495201 100644 +--- a/drivers/platform/surface/surface_hotplug.c ++++ b/drivers/platform/surface/surface_hotplug.c +@@ -10,7 +10,7 @@ + * Event signaling is handled via ACPI, which will generate the appropriate + * device-check notifications to be picked up by the PCIe hot-plug driver. + * +- * Copyright (C) 2019-2021 Maximilian Luz ++ * Copyright (C) 2019-2022 Maximilian Luz + */ + + #include +diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c +index 6373d3b5eb7f..fbf2e11fd6ce 100644 +--- a/drivers/platform/surface/surface_platform_profile.c ++++ b/drivers/platform/surface/surface_platform_profile.c +@@ -3,7 +3,7 @@ + * Surface Platform Profile / Performance Mode driver for Surface System + * Aggregator Module (thermal subsystem). + * +- * Copyright (C) 2021 Maximilian Luz ++ * Copyright (C) 2021-2022 Maximilian Luz + */ + + #include -- -2.36.0 +2.36.1 -From 33b3e3c489a43b4c71d5886e10af33473a939ca9 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 24 Feb 2022 12:02:41 +0100 -Subject: [PATCH] platform/surface: Remove Surface 3 Button driver +From 25d1faa2928596cc4902653225e57741688730a4 Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Sat, 25 Jul 2020 17:19:53 +0200 +Subject: [PATCH] i2c: acpi: Implement RawBytes read access -The Surface 3 buttons are now handled by the generic soc_button_array -driver. As part of adding support to soc_button_array the ACPI code -now instantiates a platform_device rather then an i2c_client so there -no longer is an i2c_client for this driver to bind to. +Microsoft Surface Pro 4 and Book 1 devices access the MSHW0030 I2C +device via a generic serial bus operation region and RawBytes read +access. On the Surface Book 1, this access is required to turn on (and +off) the discrete GPU. -Signed-off-by: Hans de Goede -Reviewed-by: Maximilian Luz Raw accesses assume that the writer has knowledge of the bus that + > the access is made over and the device that is being accessed. The + > protocol may only ensure that the buffer is transmitted to the + > appropriate driver, but the driver must be able to interpret the + > buffer to communicate to a register. + + Thus this implementation may likely not work on other devices + accessing I2C via the RawBytes accessor type. + +b) The MSHW0030 I2C device is an HID-over-I2C device which seems to + serve multiple functions: + + 1. It is the main access point for the legacy-type Surface Aggregator + Module (also referred to as SAM-over-HID, as opposed to the newer + SAM-over-SSH/UART). It has currently not been determined on how + support for the legacy SAM should be implemented. Likely via a + custom HID driver. + + 2. It seems to serve as the HID device for the Integrated Sensor Hub. + This might complicate matters with regards to implementing a + SAM-over-HID driver required by legacy SAM. + +In light of this, the simplest approach has been chosen for now. +However, it may make more sense regarding breakage and compatibility to +either provide functionality for replacing or enhancing the default +operation region handler via some additional API functions, or even to +completely blacklist MSHW0030 from the I2C core and provide a custom +driver for it. + +Replacing/enhancing the default operation region handler would, however, +either require some sort of secondary driver and access point for it, +from which the new API functions would be called and the new handler +(part) would be installed, or hard-coding them via some sort of +quirk-like interface into the I2C core. + +Signed-off-by: Maximilian Luz +Patchset: surface-sam-over-hid --- - drivers/platform/surface/Kconfig | 7 - - drivers/platform/surface/Makefile | 1 - - drivers/platform/surface/surface3_button.c | 247 --------------------- - 3 files changed, 255 deletions(-) - delete mode 100644 drivers/platform/surface/surface3_button.c + drivers/i2c/i2c-core-acpi.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) -diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig -index c6c3c9bd3b57..df387ac34a79 100644 ---- a/drivers/platform/surface/Kconfig -+++ b/drivers/platform/surface/Kconfig -@@ -28,13 +28,6 @@ config SURFACE3_WMI - To compile this driver as a module, choose M here: the module will - be called surface3-wmi. +diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c +index 85ed4c1d4924..942c1c9a4ea5 100644 +--- a/drivers/i2c/i2c-core-acpi.c ++++ b/drivers/i2c/i2c-core-acpi.c +@@ -624,6 +624,28 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, + return (ret == 1) ? 0 : -EIO; + } --config SURFACE_3_BUTTON -- tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet" -- depends on ACPI -- depends on KEYBOARD_GPIO && I2C ++static int acpi_gsb_i2c_write_raw_bytes(struct i2c_client *client, ++ u8 *data, u8 data_len) ++{ ++ struct i2c_msg msgs[1]; ++ int ret = AE_OK; ++ ++ msgs[0].addr = client->addr; ++ msgs[0].flags = client->flags; ++ msgs[0].len = data_len + 1; ++ msgs[0].buf = data; ++ ++ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); ++ ++ if (ret < 0) { ++ dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret); ++ return ret; ++ } ++ ++ /* 1 transfer must have completed successfully */ ++ return (ret == 1) ? 0 : -EIO; ++} ++ + static acpi_status + i2c_acpi_space_handler(u32 function, acpi_physical_address command, + u32 bits, u64 *value64, +@@ -725,6 +747,19 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command, + } + break; + ++ case ACPI_GSB_ACCESS_ATTRIB_RAW_BYTES: ++ if (action == ACPI_READ) { ++ dev_warn(&adapter->dev, ++ "protocol 0x%02x not supported for client 0x%02x\n", ++ accessor_type, client->addr); ++ ret = AE_BAD_PARAMETER; ++ goto err; ++ } else { ++ status = acpi_gsb_i2c_write_raw_bytes(client, ++ gsb->data, info->access_length); ++ } ++ break; ++ + default: + dev_warn(&adapter->dev, "protocol 0x%02x not supported for client 0x%02x\n", + accessor_type, client->addr); +-- +2.36.1 + +From 2ec19064dafe6c2150f2fab606ad38fcfdc757d0 Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Sat, 13 Feb 2021 16:41:18 +0100 +Subject: [PATCH] platform/surface: Add driver for Surface Book 1 dGPU switch + +Add driver exposing the discrete GPU power-switch of the Microsoft +Surface Book 1 to user-space. + +On the Surface Book 1, the dGPU power is controlled via the Surface +System Aggregator Module (SAM). The specific SAM-over-HID command for +this is exposed via ACPI. This module provides a simple driver exposing +the ACPI call via a sysfs parameter to user-space, so that users can +easily power-on/-off the dGPU. + +Patchset: surface-sam-over-hid +--- + drivers/platform/surface/Kconfig | 7 + + drivers/platform/surface/Makefile | 1 + + .../surface/surfacebook1_dgpu_switch.c | 162 ++++++++++++++++++ + 3 files changed, 170 insertions(+) + create mode 100644 drivers/platform/surface/surfacebook1_dgpu_switch.c + +diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig +index c685ec440535..3d3659b87ba4 100644 +--- a/drivers/platform/surface/Kconfig ++++ b/drivers/platform/surface/Kconfig +@@ -133,6 +133,13 @@ config SURFACE_AGGREGATOR_REGISTRY + the respective client devices. Drivers for these devices still need to + be selected via the other options. + ++config SURFACE_BOOK1_DGPU_SWITCH ++ tristate "Surface Book 1 dGPU Switch Driver" ++ depends on SYSFS ++ help ++ This driver provides a sysfs switch to set the power-state of the ++ discrete GPU found on the Microsoft Surface Book 1. ++ + config SURFACE_DTX + tristate "Surface DTX (Detachment System) Driver" + depends on SURFACE_AGGREGATOR +diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile +index fccd33e6780d..20408730f425 100644 +--- a/drivers/platform/surface/Makefile ++++ b/drivers/platform/surface/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/ + obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o + obj-$(CONFIG_SURFACE_AGGREGATOR_HUB) += surface_aggregator_hub.o + obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o ++obj-$(CONFIG_SURFACE_BOOK1_DGPU_SWITCH) += surfacebook1_dgpu_switch.o + obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o + obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o + obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o +diff --git a/drivers/platform/surface/surfacebook1_dgpu_switch.c b/drivers/platform/surface/surfacebook1_dgpu_switch.c +new file mode 100644 +index 000000000000..8b816ed8f35c +--- /dev/null ++++ b/drivers/platform/surface/surfacebook1_dgpu_switch.c +@@ -0,0 +1,162 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#include ++#include ++#include ++#include ++ ++ ++#ifdef pr_fmt ++#undef pr_fmt ++#endif ++#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ ++ ++ ++static const guid_t dgpu_sw_guid = GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, ++ 0x95, 0xed, 0xab, 0x16, 0x65, 0x49, 0x80, 0x35); ++ ++#define DGPUSW_ACPI_PATH_DSM "\\_SB_.PCI0.LPCB.EC0_.VGBI" ++#define DGPUSW_ACPI_PATH_HGON "\\_SB_.PCI0.RP05.HGON" ++#define DGPUSW_ACPI_PATH_HGOF "\\_SB_.PCI0.RP05.HGOF" ++ ++ ++static int sb1_dgpu_sw_dsmcall(void) ++{ ++ union acpi_object *ret; ++ acpi_handle handle; ++ acpi_status status; ++ ++ status = acpi_get_handle(NULL, DGPUSW_ACPI_PATH_DSM, &handle); ++ if (status) ++ return -EINVAL; ++ ++ ret = acpi_evaluate_dsm_typed(handle, &dgpu_sw_guid, 1, 1, NULL, ACPI_TYPE_BUFFER); ++ if (!ret) ++ return -EINVAL; ++ ++ ACPI_FREE(ret); ++ return 0; ++} ++ ++static int sb1_dgpu_sw_hgon(void) ++{ ++ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; ++ acpi_status status; ++ ++ status = acpi_evaluate_object(NULL, DGPUSW_ACPI_PATH_HGON, NULL, &buf); ++ if (status) { ++ pr_err("failed to run HGON: %d\n", status); ++ return -EINVAL; ++ } ++ ++ if (buf.pointer) ++ ACPI_FREE(buf.pointer); ++ ++ pr_info("turned-on dGPU via HGON\n"); ++ return 0; ++} ++ ++static int sb1_dgpu_sw_hgof(void) ++{ ++ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; ++ acpi_status status; ++ ++ status = acpi_evaluate_object(NULL, DGPUSW_ACPI_PATH_HGOF, NULL, &buf); ++ if (status) { ++ pr_err("failed to run HGOF: %d\n", status); ++ return -EINVAL; ++ } ++ ++ if (buf.pointer) ++ ACPI_FREE(buf.pointer); ++ ++ pr_info("turned-off dGPU via HGOF\n"); ++ return 0; ++} ++ ++ ++static ssize_t dgpu_dsmcall_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ int status, value; ++ ++ status = kstrtoint(buf, 0, &value); ++ if (status < 0) ++ return status; ++ ++ if (value != 1) ++ return -EINVAL; ++ ++ status = sb1_dgpu_sw_dsmcall(); ++ ++ return status < 0 ? status : len; ++} ++ ++static ssize_t dgpu_power_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ bool power; ++ int status; ++ ++ status = kstrtobool(buf, &power); ++ if (status < 0) ++ return status; ++ ++ if (power) ++ status = sb1_dgpu_sw_hgon(); ++ else ++ status = sb1_dgpu_sw_hgof(); ++ ++ return status < 0 ? status : len; ++} ++ ++static DEVICE_ATTR_WO(dgpu_dsmcall); ++static DEVICE_ATTR_WO(dgpu_power); ++ ++static struct attribute *sb1_dgpu_sw_attrs[] = { ++ &dev_attr_dgpu_dsmcall.attr, ++ &dev_attr_dgpu_power.attr, ++ NULL, ++}; ++ ++static const struct attribute_group sb1_dgpu_sw_attr_group = { ++ .attrs = sb1_dgpu_sw_attrs, ++}; ++ ++ ++static int sb1_dgpu_sw_probe(struct platform_device *pdev) ++{ ++ return sysfs_create_group(&pdev->dev.kobj, &sb1_dgpu_sw_attr_group); ++} ++ ++static int sb1_dgpu_sw_remove(struct platform_device *pdev) ++{ ++ sysfs_remove_group(&pdev->dev.kobj, &sb1_dgpu_sw_attr_group); ++ return 0; ++} ++ ++/* ++ * The dGPU power seems to be actually handled by MSHW0040. However, that is ++ * also the power-/volume-button device with a mainline driver. So let's use ++ * MSHW0041 instead for now, which seems to be the LTCH (latch/DTX) device. ++ */ ++static const struct acpi_device_id sb1_dgpu_sw_match[] = { ++ { "MSHW0041", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(acpi, sb1_dgpu_sw_match); ++ ++static struct platform_driver sb1_dgpu_sw = { ++ .probe = sb1_dgpu_sw_probe, ++ .remove = sb1_dgpu_sw_remove, ++ .driver = { ++ .name = "surfacebook1_dgpu_switch", ++ .acpi_match_table = sb1_dgpu_sw_match, ++ .probe_type = PROBE_PREFER_ASYNCHRONOUS, ++ }, ++}; ++module_platform_driver(sb1_dgpu_sw); ++ ++MODULE_AUTHOR("Maximilian Luz "); ++MODULE_DESCRIPTION("Discrete GPU Power-Switch for Surface Book 1"); ++MODULE_LICENSE("GPL"); +-- +2.36.1 + +From 0e6a0910bdec9c3b4d9658207c7b2cde6d86d375 Mon Sep 17 00:00:00 2001 +From: Sachi King +Date: Tue, 5 Oct 2021 00:05:09 +1100 +Subject: [PATCH] Input: soc_button_array - support AMD variant Surface devices + +The power button on the AMD variant of the Surface Laptop uses the +same MSHW0040 device ID as the 5th and later generation of Surface +devices, however they report 0 for their OEM platform revision. As the +_DSM does not exist on the devices requiring special casing, check for +the existance of the _DSM to determine if soc_button_array should be +loaded. + +Fixes: c394159310d0 ("Input: soc_button_array - add support for newer surface devices") +Co-developed-by: Maximilian Luz + +Signed-off-by: Sachi King +Patchset: surface-button +--- + drivers/input/misc/soc_button_array.c | 33 +++++++-------------------- + 1 file changed, 8 insertions(+), 25 deletions(-) + +diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c +index cb6ec59a045d..4e8944f59def 100644 +--- a/drivers/input/misc/soc_button_array.c ++++ b/drivers/input/misc/soc_button_array.c +@@ -474,8 +474,8 @@ static const struct soc_device_data soc_device_INT33D3 = { + * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned + * devices use MSHW0040 for power and volume buttons, however the way they + * have to be addressed differs. Make sure that we only load this drivers +- * for the correct devices by checking the OEM Platform Revision provided by +- * the _DSM method. ++ * for the correct devices by checking if the OEM Platform Revision DSM call ++ * exists. + */ + #define MSHW0040_DSM_REVISION 0x01 + #define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision +@@ -486,31 +486,14 @@ static const guid_t MSHW0040_DSM_UUID = + static int soc_device_check_MSHW0040(struct device *dev) + { + acpi_handle handle = ACPI_HANDLE(dev); +- union acpi_object *result; +- u64 oem_platform_rev = 0; // valid revisions are nonzero +- +- // get OEM platform revision +- result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID, +- MSHW0040_DSM_REVISION, +- MSHW0040_DSM_GET_OMPR, NULL, +- ACPI_TYPE_INTEGER); +- +- if (result) { +- oem_platform_rev = result->integer.value; +- ACPI_FREE(result); +- } +- +- /* +- * If the revision is zero here, the _DSM evaluation has failed. This +- * indicates that we have a Pro 4 or Book 1 and this driver should not +- * be used. +- */ +- if (oem_platform_rev == 0) +- return -ENODEV; ++ bool exists; + +- dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev); ++ // check if OEM platform revision DSM call exists ++ exists = acpi_check_dsm(handle, &MSHW0040_DSM_UUID, ++ MSHW0040_DSM_REVISION, ++ BIT(MSHW0040_DSM_GET_OMPR)); + +- return 0; ++ return exists ? 0 : -ENODEV; + } + + /* +-- +2.36.1 + +From 6224cf2d064ad98e8aa6153be11cbee3fc760cdc Mon Sep 17 00:00:00 2001 +From: Sachi King +Date: Tue, 5 Oct 2021 00:22:57 +1100 +Subject: [PATCH] platform/surface: surfacepro3_button: don't load on amd + variant + +The AMD variant of the Surface Laptop report 0 for their OEM platform +revision. The Surface devices that require the surfacepro3_button +driver do not have the _DSM that gets the OEM platform revision. If the +method does not exist, load surfacepro3_button. + +Fixes: 64dd243d7356 ("platform/x86: surfacepro3_button: Fix device check") +Co-developed-by: Maximilian Luz + +Signed-off-by: Sachi King +Patchset: surface-button +--- + drivers/platform/surface/surfacepro3_button.c | 30 ++++--------------- + 1 file changed, 6 insertions(+), 24 deletions(-) + +diff --git a/drivers/platform/surface/surfacepro3_button.c b/drivers/platform/surface/surfacepro3_button.c +index 242fb690dcaf..30eea54dbb47 100644 +--- a/drivers/platform/surface/surfacepro3_button.c ++++ b/drivers/platform/surface/surfacepro3_button.c +@@ -149,7 +149,8 @@ static int surface_button_resume(struct device *dev) + /* + * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device + * ID (MSHW0040) for the power/volume buttons. Make sure this is the right +- * device by checking for the _DSM method and OEM Platform Revision. ++ * device by checking for the _DSM method and OEM Platform Revision DSM ++ * function. + * + * Returns true if the driver should bind to this device, i.e. the device is + * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1. +@@ -157,30 +158,11 @@ static int surface_button_resume(struct device *dev) + static bool surface_button_check_MSHW0040(struct acpi_device *dev) + { + acpi_handle handle = dev->handle; +- union acpi_object *result; +- u64 oem_platform_rev = 0; // valid revisions are nonzero +- +- // get OEM platform revision +- result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID, +- MSHW0040_DSM_REVISION, +- MSHW0040_DSM_GET_OMPR, +- NULL, ACPI_TYPE_INTEGER); +- +- /* +- * If evaluating the _DSM fails, the method is not present. This means +- * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we +- * should use this driver. We use revision 0 indicating it is +- * unavailable. +- */ +- +- if (result) { +- oem_platform_rev = result->integer.value; +- ACPI_FREE(result); +- } +- +- dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev); + +- return oem_platform_rev == 0; ++ // make sure that OEM platform revision DSM call does not exist ++ return !acpi_check_dsm(handle, &MSHW0040_DSM_UUID, ++ MSHW0040_DSM_REVISION, ++ BIT(MSHW0040_DSM_GET_OMPR)); + } + + +-- +2.36.1 + +From a8a665d668c8b626813a8fefe5c2be602fdabf31 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 24 Feb 2022 12:02:40 +0100 +Subject: [PATCH] Input: soc_button_array - add support for Microsoft Surface 3 + (MSHW0028) buttons + +The drivers/platform/surface/surface3_button.c code is alsmost a 1:1 copy +of the soc_button_array code. + +The only big difference is that it binds to an i2c_client rather then to +a platform_device. The cause of this is the ACPI resources for the MSHW0028 +device containing a bogus I2cSerialBusV2 resource which causes the kernel +to instantiate an i2c_client for it instead of a platform_device. + +Add "MSHW0028" to the ignore_serial_bus_ids[] list in drivers/apci/scan.c, +so that a platform_device will be instantiated and add support for +the MSHW0028 HID to soc_button_array. + +This fully replaces surface3_button, which will be removed in a separate +commit (since it binds to the now no longer created i2c_client it no +longer does anyyhing after this commit). + +Note the MSHW0028 id is used by Microsoft to describe the tablet buttons on +both the Surface 3 and the Surface 3 Pro and the actual API/implementation +for the Surface 3 Pro is quite different. The changes in this commit should +not impact the separate surfacepro3_button driver: + +1. Because of the bogus I2cSerialBusV2 resource problem that driver binds + to the acpi_device itself, so instantiating a platform_device instead of + an i2c_client does not matter. + +2. The soc_button_array driver will not bind to the MSHW0028 device on + the Surface 3 Pro, because it has no GPIO resources. + +Signed-off-by: Hans de Goede +Reviewed-by: Maximilian Luz +Date: Thu, 24 Feb 2022 12:02:41 +0100 +Subject: [PATCH] platform/surface: Remove Surface 3 Button driver + +The Surface 3 buttons are now handled by the generic soc_button_array +driver. As part of adding support to soc_button_array the ACPI code +now instantiates a platform_device rather then an i2c_client so there +no longer is an i2c_client for this driver to bind to. + +Signed-off-by: Hans de Goede +Reviewed-by: Maximilian Luz dev; -- struct surface3_button_data *priv; -- struct platform_device *pd; -- int i; -- int error; -- -- if (strncmp(acpi_device_bid(ACPI_COMPANION(&client->dev)), -- SURFACE_BUTTON_OBJ_NAME, -- strlen(SURFACE_BUTTON_OBJ_NAME))) -- return -ENODEV; -- -- error = gpiod_count(dev, NULL); -- if (error < 0) { -- dev_dbg(dev, "no GPIO attached, ignoring...\n"); -- return error; -- } -- -- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -- if (!priv) -- return -ENOMEM; +- struct device *dev = &client->dev; +- struct surface3_button_data *priv; +- struct platform_device *pd; +- int i; +- int error; +- +- if (strncmp(acpi_device_bid(ACPI_COMPANION(&client->dev)), +- SURFACE_BUTTON_OBJ_NAME, +- strlen(SURFACE_BUTTON_OBJ_NAME))) +- return -ENODEV; +- +- error = gpiod_count(dev, NULL); +- if (error < 0) { +- dev_dbg(dev, "no GPIO attached, ignoring...\n"); +- return error; +- } +- +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- i2c_set_clientdata(client, priv); +- +- for (i = 0; i < BUTTON_TYPES; i++) { +- pd = surface3_button_device_create(client, +- surface3_button_surface3, +- i == 0); +- if (IS_ERR(pd)) { +- error = PTR_ERR(pd); +- if (error != -ENODEV) { +- surface3_button_remove(client); +- return error; +- } +- continue; +- } +- +- priv->children[i] = pd; +- } +- +- if (!priv->children[0] && !priv->children[1]) +- return -ENODEV; +- +- return 0; +-} +- +-static const struct i2c_device_id surface3_id[] = { +- { } +-}; +-MODULE_DEVICE_TABLE(i2c, surface3_id); +- +-static struct i2c_driver surface3_driver = { +- .probe = surface3_button_probe, +- .remove = surface3_button_remove, +- .id_table = surface3_id, +- .driver = { +- .name = "surface3", +- .acpi_match_table = ACPI_PTR(surface3_acpi_match), +- }, +-}; +-module_i2c_driver(surface3_driver); +- +-MODULE_AUTHOR("Benjamin Tissoires "); +-MODULE_DESCRIPTION("surface3 button array driver"); +-MODULE_LICENSE("GPL v2"); +-- +2.36.1 + +From f5d22c97a860e9002ad31c8bf1c00b629c432ba7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= +Date: Thu, 5 Nov 2020 13:09:45 +0100 +Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when + suspending + +The Type Cover for Microsoft Surface devices supports a special usb +control request to disable or enable the built-in keyboard backlight. +On Windows, this request happens when putting the device into suspend or +resuming it, without it the backlight of the Type Cover will remain +enabled for some time even though the computer is suspended, which looks +weird to the user. + +So add support for this special usb control request to hid-multitouch, +which is the driver that's handling the Type Cover. + +The reason we have to use a pm_notifier for this instead of the usual +suspend/resume methods is that those won't get called in case the usb +device is already autosuspended. + +Also, if the device is autosuspended, we have to briefly autoresume it +in order to send the request. Doing that should be fine, the usb-core +driver does something similar during suspend inside choose_wakeup(). + +To make sure we don't send that request to every device but only to +devices which support it, add a new quirk +MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER to hid-multitouch. For now this quirk +is only enabled for the usb id of the Surface Pro 2017 Type Cover, which +is where I confirmed that it's working. + +Patchset: surface-typecover +--- + drivers/hid/hid-multitouch.c | 100 ++++++++++++++++++++++++++++++++++- + 1 file changed, 98 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 99eabfb4145b..bbfcae39f375 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -34,7 +34,10 @@ + #include + #include + #include ++#include + #include ++#include ++#include + #include + #include + #include +@@ -47,6 +50,7 @@ MODULE_DESCRIPTION("HID multitouch panels"); + MODULE_LICENSE("GPL"); + + #include "hid-ids.h" ++#include "usbhid/usbhid.h" + + /* quirks to control the device */ + #define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0) +@@ -71,12 +75,15 @@ MODULE_LICENSE("GPL"); + #define MT_QUIRK_SEPARATE_APP_REPORT BIT(19) + #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) + #define MT_QUIRK_DISABLE_WAKEUP BIT(21) ++#define MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT BIT(22) + + #define MT_INPUTMODE_TOUCHSCREEN 0x02 + #define MT_INPUTMODE_TOUCHPAD 0x03 + + #define MT_BUTTONTYPE_CLICKPAD 0 + ++#define MS_TYPE_COVER_FEATURE_REPORT_USAGE 0xff050086 ++ + enum latency_mode { + HID_LATENCY_NORMAL = 0, + HID_LATENCY_HIGH = 1, +@@ -168,6 +175,8 @@ struct mt_device { + + struct list_head applications; + struct list_head reports; ++ ++ struct notifier_block pm_notifier; + }; + + static void mt_post_parse_default_settings(struct mt_device *td, +@@ -211,6 +220,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); + #define MT_CLS_GOOGLE 0x0111 + #define MT_CLS_RAZER_BLADE_STEALTH 0x0112 + #define MT_CLS_SMART_TECH 0x0113 ++#define MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER 0x0114 + + #define MT_DEFAULT_MAXCONTACT 10 + #define MT_MAX_MAXCONTACT 250 +@@ -386,6 +396,16 @@ static const struct mt_class mt_classes[] = { + MT_QUIRK_CONTACT_CNT_ACCURATE | + MT_QUIRK_SEPARATE_APP_REPORT, + }, ++ { .name = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER, ++ .quirks = MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT | ++ MT_QUIRK_ALWAYS_VALID | ++ MT_QUIRK_IGNORE_DUPLICATES | ++ MT_QUIRK_HOVERING | ++ MT_QUIRK_CONTACT_CNT_ACCURATE | ++ MT_QUIRK_STICKY_FINGERS | ++ MT_QUIRK_WIN8_PTP_BUTTONS, ++ .export_all_inputs = true ++ }, + { } + }; + +@@ -1695,6 +1715,69 @@ static void mt_expired_timeout(struct timer_list *t) + clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); + } + ++static void get_type_cover_backlight_field(struct hid_device *hdev, ++ struct hid_field **field) ++{ ++ struct hid_report_enum *rep_enum; ++ struct hid_report *rep; ++ struct hid_field *cur_field; ++ int i, j; ++ ++ rep_enum = &hdev->report_enum[HID_FEATURE_REPORT]; ++ list_for_each_entry(rep, &rep_enum->report_list, list) { ++ for (i = 0; i < rep->maxfield; i++) { ++ cur_field = rep->field[i]; ++ ++ for (j = 0; j < cur_field->maxusage; j++) { ++ if (cur_field->usage[j].hid ++ == MS_TYPE_COVER_FEATURE_REPORT_USAGE) { ++ *field = cur_field; ++ return; ++ } ++ } ++ } ++ } ++} ++ ++static void update_keyboard_backlight(struct hid_device *hdev, bool enabled) ++{ ++ struct usb_device *udev = hid_to_usb_dev(hdev); ++ struct hid_field *field = NULL; ++ ++ /* Wake up the device in case it's already suspended */ ++ pm_runtime_get_sync(&udev->dev); ++ ++ get_type_cover_backlight_field(hdev, &field); ++ if (!field) { ++ hid_err(hdev, "couldn't find backlight field\n"); ++ goto out; ++ } ++ ++ field->value[field->index] = enabled ? 0x01ff00ff : 0x00ff00ff; ++ hid_hw_request(hdev, field->report, HID_REQ_SET_REPORT); ++ ++out: ++ pm_runtime_put_sync(&udev->dev); ++} ++ ++static int mt_pm_notifier(struct notifier_block *notifier, ++ unsigned long pm_event, ++ void *unused) ++{ ++ struct mt_device *td = ++ container_of(notifier, struct mt_device, pm_notifier); ++ struct hid_device *hdev = td->hdev; ++ ++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT) { ++ if (pm_event == PM_SUSPEND_PREPARE) ++ update_keyboard_backlight(hdev, 0); ++ else if (pm_event == PM_POST_SUSPEND) ++ update_keyboard_backlight(hdev, 1); ++ } ++ ++ return NOTIFY_DONE; ++} ++ + static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int ret, i; +@@ -1718,6 +1801,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) + td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; + hid_set_drvdata(hdev, td); + ++ td->pm_notifier.notifier_call = mt_pm_notifier; ++ register_pm_notifier(&td->pm_notifier); ++ + INIT_LIST_HEAD(&td->applications); + INIT_LIST_HEAD(&td->reports); + +@@ -1747,15 +1833,19 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) + timer_setup(&td->release_timer, mt_expired_timeout, 0); + + ret = hid_parse(hdev); +- if (ret != 0) ++ if (ret != 0) { ++ unregister_pm_notifier(&td->pm_notifier); + return ret; ++ } + + if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID) + mt_fix_const_fields(hdev, HID_DG_CONTACTID); + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); +- if (ret) ++ if (ret) { ++ unregister_pm_notifier(&td->pm_notifier); + return ret; ++ } + + ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); + if (ret) +@@ -1807,6 +1897,7 @@ static void mt_remove(struct hid_device *hdev) + { + struct mt_device *td = hid_get_drvdata(hdev); + ++ unregister_pm_notifier(&td->pm_notifier); + del_timer_sync(&td->release_timer); + + sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); +@@ -2174,6 +2265,11 @@ static const struct hid_device_id mt_devices[] = { + MT_USB_DEVICE(USB_VENDOR_ID_XIROKU, + USB_DEVICE_ID_XIROKU_CSR2) }, + ++ /* Microsoft Surface type cover */ ++ { .driver_data = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER, ++ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, ++ USB_VENDOR_ID_MICROSOFT, 0x09c0) }, ++ + /* Google MT devices */ + { .driver_data = MT_CLS_GOOGLE, + HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE, +-- +2.36.1 + +From f8ac6cc2a4f1f3020b1bcb476dc355a0e3d938ce Mon Sep 17 00:00:00 2001 +From: PJungkamp +Date: Fri, 25 Feb 2022 12:04:25 +0100 +Subject: [PATCH] hid/multitouch: Add support for surface pro type cover tablet + switch + +The Surface Pro Type Cover has several non standard HID usages in it's +hid report descriptor. +I noticed that, upon folding the typecover back, a vendor specific range +of 4 32 bit integer hid usages is transmitted. +Only the first byte of the message seems to convey reliable information +about the keyboard state. + +0x22 => Normal (keys enabled) +0x33 => Folded back (keys disabled) +0x53 => Rotated left/right side up (keys disabled) +0x13 => Cover closed (keys disabled) +0x43 => Folded back and Tablet upside down (keys disabled) +This list may not be exhaustive. + +The tablet mode switch will be disabled for a value of 0x22 and enabled +on any other value. + +Patchset: surface-typecover +--- + drivers/hid/hid-multitouch.c | 148 +++++++++++++++++++++++++++++------ + 1 file changed, 122 insertions(+), 26 deletions(-) + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index bbfcae39f375..d53228452501 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -76,6 +76,7 @@ MODULE_LICENSE("GPL"); + #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) + #define MT_QUIRK_DISABLE_WAKEUP BIT(21) + #define MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT BIT(22) ++#define MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH BIT(23) + + #define MT_INPUTMODE_TOUCHSCREEN 0x02 + #define MT_INPUTMODE_TOUCHPAD 0x03 +@@ -83,6 +84,8 @@ MODULE_LICENSE("GPL"); + #define MT_BUTTONTYPE_CLICKPAD 0 + + #define MS_TYPE_COVER_FEATURE_REPORT_USAGE 0xff050086 ++#define MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE 0xff050072 ++#define MS_TYPE_COVER_APPLICATION 0xff050050 + + enum latency_mode { + HID_LATENCY_NORMAL = 0, +@@ -398,6 +401,7 @@ static const struct mt_class mt_classes[] = { + }, + { .name = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER, + .quirks = MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT | ++ MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH | + MT_QUIRK_ALWAYS_VALID | + MT_QUIRK_IGNORE_DUPLICATES | + MT_QUIRK_HOVERING | +@@ -1357,6 +1361,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + field->application != HID_CP_CONSUMER_CONTROL && + field->application != HID_GD_WIRELESS_RADIO_CTLS && + field->application != HID_GD_SYSTEM_MULTIAXIS && ++ !(field->application == MS_TYPE_COVER_APPLICATION && ++ application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH && ++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) && + !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS && + application->quirks & MT_QUIRK_ASUS_CUSTOM_UP)) + return -1; +@@ -1384,6 +1391,21 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + return 1; + } + ++ /* ++ * The Microsoft Surface Pro Typecover has a non-standard HID ++ * tablet mode switch on a vendor specific usage page with vendor ++ * specific usage. ++ */ ++ if (field->application == MS_TYPE_COVER_APPLICATION && ++ application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH && ++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) { ++ usage->type = EV_SW; ++ usage->code = SW_TABLET_MODE; ++ *max = SW_MAX; ++ *bit = hi->input->swbit; ++ return 1; ++ } ++ + if (rdata->is_mt_collection) + return mt_touch_input_mapping(hdev, hi, field, usage, bit, max, + application); +@@ -1405,6 +1427,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, + { + struct mt_device *td = hid_get_drvdata(hdev); + struct mt_report_data *rdata; ++ struct input_dev *input; + + rdata = mt_find_report_data(td, field->report); + if (rdata && rdata->is_mt_collection) { +@@ -1412,6 +1435,19 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, + return -1; + } + ++ /* ++ * We own an input device which acts as a tablet mode switch for ++ * the Surface Pro Typecover. ++ */ ++ if (field->application == MS_TYPE_COVER_APPLICATION && ++ rdata->application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH && ++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) { ++ input = hi->input; ++ input_set_capability(input, EV_SW, SW_TABLET_MODE); ++ input_report_switch(input, SW_TABLET_MODE, 0); ++ return -1; ++ } ++ + /* let hid-core decide for the others */ + return 0; + } +@@ -1421,11 +1457,21 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, + { + struct mt_device *td = hid_get_drvdata(hid); + struct mt_report_data *rdata; ++ struct input_dev *input; + + rdata = mt_find_report_data(td, field->report); + if (rdata && rdata->is_mt_collection) + return mt_touch_event(hid, field, usage, value); + ++ if (field->application == MS_TYPE_COVER_APPLICATION && ++ rdata->application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH && ++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) { ++ input = field->hidinput->input; ++ input_report_switch(input, SW_TABLET_MODE, (value & 0xFF) != 0x22); ++ input_sync(input); ++ return 1; ++ } ++ + return 0; + } + +@@ -1578,6 +1624,42 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app) + app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; + } + ++static int get_type_cover_field(struct hid_report_enum *rep_enum, ++ struct hid_field **field, int usage) ++{ ++ struct hid_report *rep; ++ struct hid_field *cur_field; ++ int i, j; ++ ++ list_for_each_entry(rep, &rep_enum->report_list, list) { ++ for (i = 0; i < rep->maxfield; i++) { ++ cur_field = rep->field[i]; ++ if (cur_field->application != MS_TYPE_COVER_APPLICATION) ++ continue; ++ for (j = 0; j < cur_field->maxusage; j++) { ++ if (cur_field->usage[j].hid == usage) { ++ *field = cur_field; ++ return true; ++ } ++ } ++ } ++ } ++ return false; ++} ++ ++static void request_type_cover_tablet_mode_switch(struct hid_device *hdev) ++{ ++ struct hid_field *field; ++ ++ if (get_type_cover_field(&hdev->report_enum[HID_INPUT_REPORT], ++ &field, ++ MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE)) { ++ hid_hw_request(hdev, field->report, HID_REQ_GET_REPORT); ++ } else { ++ hid_err(hdev, "couldn't find tablet mode field\n"); ++ } ++} ++ + static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) + { + struct mt_device *td = hid_get_drvdata(hdev); +@@ -1627,6 +1709,13 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) + /* force BTN_STYLUS to allow tablet matching in udev */ + __set_bit(BTN_STYLUS, hi->input->keybit); + break; ++ case MS_TYPE_COVER_APPLICATION: ++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) { ++ suffix = "Tablet Mode Switch"; ++ request_type_cover_tablet_mode_switch(hdev); ++ break; ++ } ++ fallthrough; + default: + suffix = "UNKNOWN"; + break; +@@ -1715,30 +1804,6 @@ static void mt_expired_timeout(struct timer_list *t) + clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); + } + +-static void get_type_cover_backlight_field(struct hid_device *hdev, +- struct hid_field **field) +-{ +- struct hid_report_enum *rep_enum; +- struct hid_report *rep; +- struct hid_field *cur_field; +- int i, j; - -- i2c_set_clientdata(client, priv); +- rep_enum = &hdev->report_enum[HID_FEATURE_REPORT]; +- list_for_each_entry(rep, &rep_enum->report_list, list) { +- for (i = 0; i < rep->maxfield; i++) { +- cur_field = rep->field[i]; - -- for (i = 0; i < BUTTON_TYPES; i++) { -- pd = surface3_button_device_create(client, -- surface3_button_surface3, -- i == 0); -- if (IS_ERR(pd)) { -- error = PTR_ERR(pd); -- if (error != -ENODEV) { -- surface3_button_remove(client); -- return error; +- for (j = 0; j < cur_field->maxusage; j++) { +- if (cur_field->usage[j].hid +- == MS_TYPE_COVER_FEATURE_REPORT_USAGE) { +- *field = cur_field; +- return; +- } - } -- continue; - } -- -- priv->children[i] = pd; - } +-} - -- if (!priv->children[0] && !priv->children[1]) -- return -ENODEV; -- + static void update_keyboard_backlight(struct hid_device *hdev, bool enabled) + { + struct usb_device *udev = hid_to_usb_dev(hdev); +@@ -1747,8 +1812,9 @@ static void update_keyboard_backlight(struct hid_device *hdev, bool enabled) + /* Wake up the device in case it's already suspended */ + pm_runtime_get_sync(&udev->dev); + +- get_type_cover_backlight_field(hdev, &field); +- if (!field) { ++ if (!get_type_cover_field(&hdev->report_enum[HID_FEATURE_REPORT], ++ &field, ++ MS_TYPE_COVER_FEATURE_REPORT_USAGE)) { + hid_err(hdev, "couldn't find backlight field\n"); + goto out; + } +@@ -1874,13 +1940,24 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state) + + static int mt_reset_resume(struct hid_device *hdev) + { ++ struct mt_device *td = hid_get_drvdata(hdev); ++ + mt_release_contacts(hdev); + mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); ++ ++ /* Request an update on the typecover folding state on resume ++ * after reset. ++ */ ++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) ++ request_type_cover_tablet_mode_switch(hdev); ++ + return 0; + } + + static int mt_resume(struct hid_device *hdev) + { ++ struct mt_device *td = hid_get_drvdata(hdev); ++ + /* Some Elan legacy devices require SET_IDLE to be set on resume. + * It should be safe to send it to other devices too. + * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */ +@@ -1889,6 +1966,10 @@ static int mt_resume(struct hid_device *hdev) + + mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + ++ /* Request an update on the typecover folding state on resume. */ ++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) ++ request_type_cover_tablet_mode_switch(hdev); ++ + return 0; + } + #endif +@@ -1896,6 +1977,21 @@ static int mt_resume(struct hid_device *hdev) + static void mt_remove(struct hid_device *hdev) + { + struct mt_device *td = hid_get_drvdata(hdev); ++ struct hid_field *field; ++ struct input_dev *input; ++ ++ /* Reset tablet mode switch on disconnect. */ ++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) { ++ if (get_type_cover_field(&hdev->report_enum[HID_INPUT_REPORT], ++ &field, ++ MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE)) { ++ input = field->hidinput->input; ++ input_report_switch(input, SW_TABLET_MODE, 0); ++ input_sync(input); ++ } else { ++ hid_err(hdev, "couldn't find tablet mode field\n"); ++ } ++ } + + unregister_pm_notifier(&td->pm_notifier); + del_timer_sync(&td->release_timer); +-- +2.36.1 + +From 93fa65ace198e7abaa1a27e42f3ebcf509022902 Mon Sep 17 00:00:00 2001 +From: Werner Sembach +Date: Wed, 27 Apr 2022 17:40:53 +0200 +Subject: [PATCH] ACPI: battery: Make "not-charging" the default on no charging + or full info + +When the battery is neither charging or discharging and is not full, +"not-charging" is a useful status description for the case in general. +Currently this state is set as "unknown" by default, expect when this is +explicitly replaced with "not-charging" on a per device or per vendor +basis. + +A lot of devices have this state without a BIOS specification available +explicitly describing it. e.g. some current Clevo barebones have a BIOS +setting to stop charging at a user defined battery level. + +Signed-off-by: Werner Sembach +Signed-off-by: Rafael J. Wysocki +Patchset: surface-battery +--- + drivers/acpi/battery.c | 24 +----------------------- + 1 file changed, 1 insertion(+), 23 deletions(-) + +diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c +index dc208f5f5a1f..306513fec1e1 100644 +--- a/drivers/acpi/battery.c ++++ b/drivers/acpi/battery.c +@@ -52,7 +52,6 @@ static bool battery_driver_registered; + static int battery_bix_broken_package; + static int battery_notification_delay_ms; + static int battery_ac_is_broken; +-static int battery_quirk_notcharging; + static unsigned int cache_time = 1000; + module_param(cache_time, uint, 0644); + MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); +@@ -216,10 +215,8 @@ static int acpi_battery_get_property(struct power_supply *psy, + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else if (acpi_battery_is_charged(battery)) + val->intval = POWER_SUPPLY_STATUS_FULL; +- else if (battery_quirk_notcharging) +- val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + else +- val->intval = POWER_SUPPLY_STATUS_UNKNOWN; ++ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = acpi_battery_present(battery); +@@ -1105,12 +1102,6 @@ battery_ac_is_broken_quirk(const struct dmi_system_id *d) + return 0; + } + +-static int __init battery_quirk_not_charging(const struct dmi_system_id *d) +-{ +- battery_quirk_notcharging = 1; - return 0; -} -- --static const struct i2c_device_id surface3_id[] = { -- { } --}; --MODULE_DEVICE_TABLE(i2c, surface3_id); -- --static struct i2c_driver surface3_driver = { -- .probe = surface3_button_probe, -- .remove = surface3_button_remove, -- .id_table = surface3_id, -- .driver = { -- .name = "surface3", -- .acpi_match_table = ACPI_PTR(surface3_acpi_match), -- }, --}; --module_i2c_driver(surface3_driver); -- --MODULE_AUTHOR("Benjamin Tissoires "); --MODULE_DESCRIPTION("surface3 button array driver"); --MODULE_LICENSE("GPL v2"); +- + static const struct dmi_system_id bat_dmi_table[] __initconst = { + { + /* NEC LZ750/LS */ +@@ -1139,19 +1130,6 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { + DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), + }, + }, +- { +- /* +- * On Lenovo ThinkPads the BIOS specification defines +- * a state when the bits for charging and discharging +- * are both set to 0. That state is "Not Charging". +- */ +- .callback = battery_quirk_not_charging, +- .ident = "Lenovo ThinkPad", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"), +- }, +- }, + { + /* Microsoft Surface Go 3 */ + .callback = battery_notification_delay_quirk, -- -2.36.0 +2.36.1 -From 6854ba2ebc5761be240d5fd1d57555011f307f2c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= -Date: Thu, 5 Nov 2020 13:09:45 +0100 -Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when - suspending +From a29f2ab8670becc07a56ccdfe3a7a1fe64730803 Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Wed, 25 May 2022 14:20:10 +0200 +Subject: [PATCH] HID: hid-input: add Surface Go battery quirk -The Type Cover for Microsoft Surface devices supports a special usb -control request to disable or enable the built-in keyboard backlight. -On Windows, this request happens when putting the device into suspend or -resuming it, without it the backlight of the Type Cover will remain -enabled for some time even though the computer is suspended, which looks -weird to the user. +Similar to the Surface Go (1), the (Elantech) touchscreen/digitizer in +the Surface Go 2 mistakenly reports the battery of the stylus. Instead +of over the touchsreen device, battery information is provided via +bluetooth and the touchscreen device reports an empty battery. -So add support for this special usb control request to hid-multitouch, -which is the driver that's handling the Type Cover. +Apply the HID_BATTERY_QUIRK_IGNORE quirk to to ignore this battery and +prevent the erroneous low battery warnings. -The reason we have to use a pm_notifier for this instead of the usual -suspend/resume methods is that those won't get called in case the usb -device is already autosuspended. +Signed-off-by: Maximilian Luz +Patchset: surface-battery +--- + drivers/hid/hid-ids.h | 1 + + drivers/hid/hid-input.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 78bd3ddda442..288766674c6a 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -405,6 +405,7 @@ + #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 + #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 + #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A ++#define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN 0x2A1C + + #define USB_VENDOR_ID_ELECOM 0x056e + #define USB_DEVICE_ID_ELECOM_BM084 0x0061 +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 56ec27398a00..263a977801bf 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -336,6 +336,8 @@ static const struct hid_device_id hid_battery_quirks[] = { + HID_BATTERY_QUIRK_IGNORE }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), + HID_BATTERY_QUIRK_IGNORE }, ++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN), ++ HID_BATTERY_QUIRK_IGNORE }, + {} + }; + +-- +2.36.1 -Also, if the device is autosuspended, we have to briefly autoresume it -in order to send the request. Doing that should be fine, the usb-core -driver does something similar during suspend inside choose_wakeup(). +From bab798deb7e8defbe4a0f5bb02e6254a3261c21c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:56:57 +0200 +Subject: [PATCH] ACPI: delay enumeration of devices with a _DEP pointing to an + INT3472 device -To make sure we don't send that request to every device but only to -devices which support it, add a new quirk -MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER to hid-multitouch. For now this quirk -is only enabled for the usb id of the Surface Pro 2017 Type Cover, which -is where I confirmed that it's working. +The clk and regulator frameworks expect clk/regulator consumer-devices +to have info about the consumed clks/regulators described in the device's +fw_node. -Patchset: surface-typecover +To work around cases where this info is not present in the firmware tables, +which is often the case on x86/ACPI devices, both frameworks allow the +provider-driver to attach info about consumers to the clks/regulators +when registering these. + +This causes problems with the probe ordering wrt drivers for consumers +of these clks/regulators. Since the lookups are only registered when the +provider-driver binds, trying to get these clks/regulators before then +results in a -ENOENT error for clks and a dummy regulator for regulators. + +One case where we hit this issue is camera sensors such as e.g. the OV8865 +sensor found on the Microsoft Surface Go. The sensor uses clks, regulators +and GPIOs provided by a TPS68470 PMIC which is described in an INT3472 +ACPI device. There is special platform code handling this and setting +platform_data with the necessary consumer info on the MFD cells +instantiated for the PMIC under: drivers/platform/x86/intel/int3472. + +For this to work properly the ov8865 driver must not bind to the I2C-client +for the OV8865 sensor until after the TPS68470 PMIC gpio, regulator and +clk MFD cells have all been fully setup. + +The OV8865 on the Microsoft Surface Go is just one example, all X86 +devices using the Intel IPU3 camera block found on recent Intel SoCs +have similar issues where there is an INT3472 HID ACPI-device, which +describes the clks and regulators, and the driver for this INT3472 device +must be fully initialized before the sensor driver (any sensor driver) +binds for things to work properly. + +On these devices the ACPI nodes describing the sensors all have a _DEP +dependency on the matching INT3472 ACPI device (there is one per sensor). + +This allows solving the probe-ordering problem by delaying the enumeration +(instantiation of the I2C-client in the ov8865 example) of ACPI-devices +which have a _DEP dependency on an INT3472 device. + +The new acpi_dev_ready_for_enumeration() helper used for this is also +exported because for devices, which have the enumeration_by_parent flag +set, the parent-driver will do its own scan of child ACPI devices and +it will try to enumerate those during its probe(). Code doing this such +as e.g. the i2c-core-acpi.c code must call this new helper to ensure +that it too delays the enumeration until all the _DEP dependencies are +met on devices which have the new honor_deps flag set. + +Signed-off-by: Hans de Goede +Patchset: cameras --- - drivers/hid/hid-multitouch.c | 100 ++++++++++++++++++++++++++++++++++- - 1 file changed, 98 insertions(+), 2 deletions(-) + drivers/acpi/scan.c | 3 +++ + 1 file changed, 3 insertions(+) -diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c -index 99eabfb4145b..bbfcae39f375 100644 ---- a/drivers/hid/hid-multitouch.c -+++ b/drivers/hid/hid-multitouch.c -@@ -34,7 +34,10 @@ - #include - #include - #include -+#include - #include -+#include -+#include - #include - #include - #include -@@ -47,6 +50,7 @@ MODULE_DESCRIPTION("HID multitouch panels"); - MODULE_LICENSE("GPL"); +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index c82b1bfa1c3d..2227625202aa 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -2130,6 +2130,9 @@ static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used, - #include "hid-ids.h" -+#include "usbhid/usbhid.h" + static void acpi_default_enumeration(struct acpi_device *device) + { ++ if (!acpi_dev_ready_for_enumeration(device)) ++ return; ++ + /* + * Do not enumerate devices with enumeration_by_parent flag set as + * they will be enumerated by their respective parents. +-- +2.36.1 + +From afc8f21e4250f6ff57c9385be877943253491d94 Mon Sep 17 00:00:00 2001 +From: zouxiaoh +Date: Fri, 25 Jun 2021 08:52:59 +0800 +Subject: [PATCH] iommu: intel-ipu: use IOMMU passthrough mode for Intel IPUs + +Intel IPU(Image Processing Unit) has its own (IO)MMU hardware, +The IPU driver allocates its own page table that is not mapped +via the DMA, and thus the Intel IOMMU driver blocks access giving +this error: DMAR: DRHD: handling fault status reg 3 DMAR: +[DMA Read] Request device [00:05.0] PASID ffffffff +fault addr 76406000 [fault reason 06] PTE Read access is not set +As IPU is not an external facing device which is not risky, so use +IOMMU passthrough mode for Intel IPUs. + +Change-Id: I6dcccdadac308cf42e20a18e1b593381391e3e6b +Depends-On: Iacd67578e8c6a9b9ac73285f52b4081b72fb68a6 +Tracked-On: #JIITL8-411 +Signed-off-by: Bingbu Cao +Signed-off-by: zouxiaoh +Signed-off-by: Xu Chongyang +Patchset: cameras +--- + drivers/iommu/intel/iommu.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index a91eed82bb39..0d16c6bf0e0b 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -57,6 +57,12 @@ + #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) + #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB) + #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) ++#define IS_INTEL_IPU(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \ ++ ((pdev)->device == 0x9a19 || \ ++ (pdev)->device == 0x9a39 || \ ++ (pdev)->device == 0x4e19 || \ ++ (pdev)->device == 0x465d || \ ++ (pdev)->device == 0x1919)) + #define IS_IPTS(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \ + ((pdev)->device == 0x9d3e)) + #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) +@@ -335,12 +341,14 @@ EXPORT_SYMBOL_GPL(intel_iommu_enabled); - /* quirks to control the device */ - #define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0) -@@ -71,12 +75,15 @@ MODULE_LICENSE("GPL"); - #define MT_QUIRK_SEPARATE_APP_REPORT BIT(19) - #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) - #define MT_QUIRK_DISABLE_WAKEUP BIT(21) -+#define MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT BIT(22) + static int dmar_map_gfx = 1; + static int dmar_map_ipts = 1; ++static int dmar_map_ipu = 1; + static int intel_iommu_superpage = 1; + static int iommu_identity_mapping; + static int iommu_skip_te_disable; - #define MT_INPUTMODE_TOUCHSCREEN 0x02 - #define MT_INPUTMODE_TOUCHPAD 0x03 + #define IDENTMAP_GFX 2 + #define IDENTMAP_AZALIA 4 ++#define IDENTMAP_IPU 8 + #define IDENTMAP_IPTS 16 - #define MT_BUTTONTYPE_CLICKPAD 0 + int intel_iommu_gfx_mapped; +@@ -2992,6 +3000,9 @@ static int device_def_domain_type(struct device *dev) + if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev)) + return IOMMU_DOMAIN_IDENTITY; -+#define MS_TYPE_COVER_FEATURE_REPORT_USAGE 0xff050086 ++ if ((iommu_identity_mapping & IDENTMAP_IPU) && IS_INTEL_IPU(pdev)) ++ return IOMMU_DOMAIN_IDENTITY; + - enum latency_mode { - HID_LATENCY_NORMAL = 0, - HID_LATENCY_HIGH = 1, -@@ -168,6 +175,8 @@ struct mt_device { + if ((iommu_identity_mapping & IDENTMAP_IPTS) && IS_IPTS(pdev)) + return IOMMU_DOMAIN_IDENTITY; + } +@@ -3430,6 +3441,9 @@ static int __init init_dmars(void) + if (!dmar_map_gfx) + iommu_identity_mapping |= IDENTMAP_GFX; - struct list_head applications; - struct list_head reports; ++ if (!dmar_map_ipu) ++ iommu_identity_mapping |= IDENTMAP_IPU; + -+ struct notifier_block pm_notifier; - }; + if (!dmar_map_ipts) + iommu_identity_mapping |= IDENTMAP_IPTS; - static void mt_post_parse_default_settings(struct mt_device *td, -@@ -211,6 +220,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); - #define MT_CLS_GOOGLE 0x0111 - #define MT_CLS_RAZER_BLADE_STEALTH 0x0112 - #define MT_CLS_SMART_TECH 0x0113 -+#define MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER 0x0114 +@@ -5674,6 +5688,18 @@ static void quirk_iommu_igfx(struct pci_dev *dev) + dmar_map_gfx = 0; + } + ++static void quirk_iommu_ipu(struct pci_dev *dev) ++{ ++ if (!IS_INTEL_IPU(dev)) ++ return; ++ ++ if (risky_device(dev)) ++ return; ++ ++ pci_info(dev, "Passthrough IOMMU for integrated Intel IPU\n"); ++ dmar_map_ipu = 0; ++} ++ + static void quirk_iommu_ipts(struct pci_dev *dev) + { + if (!IS_IPTS(dev)) +@@ -5685,6 +5711,7 @@ static void quirk_iommu_ipts(struct pci_dev *dev) + pci_info(dev, "Passthrough IOMMU for IPTS\n"); + dmar_map_ipts = 0; + } ++ + /* G4x/GM45 integrated gfx dmar support is totally busted. */ + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx); +@@ -5720,6 +5747,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx); + ++/* disable IPU dmar support */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_iommu_ipu); ++ + /* disable IPTS dmar support */ + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9D3E, quirk_iommu_ipts); + +-- +2.36.1 + +From 997c2b1f0237bc456dc61e869e78a4487bca07d9 Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Sun, 10 Oct 2021 20:57:02 +0200 +Subject: [PATCH] platform/x86: int3472: Enable I2c daisy chain + +The TPS68470 PMIC has an I2C passthrough mode through which I2C traffic +can be forwarded to a device connected to the PMIC as though it were +connected directly to the system bus. Enable this mode when the chip +is initialised. + +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/platform/x86/intel/int3472/tps68470.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c +index 22f61b47f9e5..e1de1ff40bba 100644 +--- a/drivers/platform/x86/intel/int3472/tps68470.c ++++ b/drivers/platform/x86/intel/int3472/tps68470.c +@@ -45,6 +45,13 @@ static int tps68470_chip_init(struct device *dev, struct regmap *regmap) + return ret; + } - #define MT_DEFAULT_MAXCONTACT 10 - #define MT_MAX_MAXCONTACT 250 -@@ -386,6 +396,16 @@ static const struct mt_class mt_classes[] = { - MT_QUIRK_CONTACT_CNT_ACCURATE | - MT_QUIRK_SEPARATE_APP_REPORT, - }, -+ { .name = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER, -+ .quirks = MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT | -+ MT_QUIRK_ALWAYS_VALID | -+ MT_QUIRK_IGNORE_DUPLICATES | -+ MT_QUIRK_HOVERING | -+ MT_QUIRK_CONTACT_CNT_ACCURATE | -+ MT_QUIRK_STICKY_FINGERS | -+ MT_QUIRK_WIN8_PTP_BUTTONS, -+ .export_all_inputs = true -+ }, - { } - }; ++ /* Enable I2C daisy chain */ ++ ret = regmap_write(regmap, TPS68470_REG_S_I2C_CTL, 0x03); ++ if (ret) { ++ dev_err(dev, "Failed to enable i2c daisy chain\n"); ++ return ret; ++ } ++ + dev_info(dev, "TPS68470 REVID: 0x%02x\n", version); -@@ -1695,6 +1715,69 @@ static void mt_expired_timeout(struct timer_list *t) - clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); - } + return 0; +-- +2.36.1 + +From c3c397ab746342288b4299b452c3ae2fd615be44 Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Thu, 28 Oct 2021 21:55:16 +0100 +Subject: [PATCH] media: i2c: Add driver for DW9719 VCM + +Add a driver for the DW9719 VCM. The driver creates a v4l2 subdevice +and registers a control to set the desired focus. + +Signed-off-by: Daniel Scally +Patchset: cameras +--- + MAINTAINERS | 7 + + drivers/media/i2c/Kconfig | 11 + + drivers/media/i2c/Makefile | 1 + + drivers/media/i2c/dw9719.c | 427 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 446 insertions(+) + create mode 100644 drivers/media/i2c/dw9719.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 4d83cd26e299..0e0e1e53e49c 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -5865,6 +5865,13 @@ T: git git://linuxtv.org/media_tree.git + F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.txt + F: drivers/media/i2c/dw9714.c -+static void get_type_cover_backlight_field(struct hid_device *hdev, -+ struct hid_field **field) ++DONGWOON DW9719 LENS VOICE COIL DRIVER ++M: Daniel Scally ++L: linux-media@vger.kernel.org ++S: Maintained ++T: git git://linuxtv.org/media_tree.git ++F: drivers/media/i2c/dw9719.c ++ + DONGWOON DW9768 LENS VOICE COIL DRIVER + M: Dongchun Zhu + L: linux-media@vger.kernel.org +diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig +index 69c56e24a612..d9fac304f451 100644 +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -1466,6 +1466,17 @@ config VIDEO_DW9714 + capability. This is designed for linear control of + voice coil motors, controlled via I2C serial interface. + ++config VIDEO_DW9719 ++ tristate "DW9719 lens voice coil support" ++ depends on I2C && VIDEO_V4L2 ++ select MEDIA_CONTROLLER ++ select VIDEO_V4L2_SUBDEV_API ++ select V4L2_ASYNC ++ help ++ This is a driver for the DW9719 camera lens voice coil. ++ This is designed for linear control of voice coil motors, ++ controlled via I2C serial interface. ++ + config VIDEO_DW9768 + tristate "DW9768 lens voice coil support" + depends on I2C && VIDEO_V4L2 +diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile +index b01f6cd05ee8..ba8b31d79222 100644 +--- a/drivers/media/i2c/Makefile ++++ b/drivers/media/i2c/Makefile +@@ -24,6 +24,7 @@ obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o + obj-$(CONFIG_VIDEO_AD5820) += ad5820.o + obj-$(CONFIG_VIDEO_AK7375) += ak7375.o + obj-$(CONFIG_VIDEO_DW9714) += dw9714.o ++obj-$(CONFIG_VIDEO_DW9719) += dw9719.o + obj-$(CONFIG_VIDEO_DW9768) += dw9768.o + obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o + obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o +diff --git a/drivers/media/i2c/dw9719.c b/drivers/media/i2c/dw9719.c +new file mode 100644 +index 000000000000..8451c75b696b +--- /dev/null ++++ b/drivers/media/i2c/dw9719.c +@@ -0,0 +1,427 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2012 Intel Corporation ++ ++/* ++ * Based on linux/modules/camera/drivers/media/i2c/imx/dw9719.c in this repo: ++ * https://github.com/ZenfoneArea/android_kernel_asus_zenfone5 ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define DW9719_MAX_FOCUS_POS 1023 ++#define DW9719_CTRL_STEPS 16 ++#define DW9719_CTRL_DELAY_US 1000 ++#define DELAY_MAX_PER_STEP_NS (1000000 * 1023) ++ ++#define DW9719_INFO 0 ++#define DW9719_ID 0xF1 ++#define DW9719_CONTROL 2 ++#define DW9719_VCM_CURRENT 3 ++ ++#define DW9719_MODE 6 ++#define DW9719_VCM_FREQ 7 ++ ++#define DW9719_MODE_SAC3 0x40 ++#define DW9719_DEFAULT_VCM_FREQ 0x60 ++#define DW9719_ENABLE_RINGING 0x02 ++ ++#define NUM_REGULATORS 2 ++ ++#define to_dw9719_device(x) container_of(x, struct dw9719_device, sd) ++ ++struct dw9719_device { ++ struct device *dev; ++ struct i2c_client *client; ++ struct regulator_bulk_data regulators[NUM_REGULATORS]; ++ struct v4l2_subdev sd; ++ ++ struct dw9719_v4l2_ctrls { ++ struct v4l2_ctrl_handler handler; ++ struct v4l2_ctrl *focus; ++ } ctrls; ++}; ++ ++static int dw9719_i2c_rd8(struct i2c_client *client, u8 reg, u8 *val) +{ -+ struct hid_report_enum *rep_enum; -+ struct hid_report *rep; -+ struct hid_field *cur_field; -+ int i, j; ++ struct i2c_msg msg[2]; ++ u8 buf[2] = { reg }; ++ int ret; + -+ rep_enum = &hdev->report_enum[HID_FEATURE_REPORT]; -+ list_for_each_entry(rep, &rep_enum->report_list, list) { -+ for (i = 0; i < rep->maxfield; i++) { -+ cur_field = rep->field[i]; ++ msg[0].addr = client->addr; ++ msg[0].flags = 0; ++ msg[0].len = 1; ++ msg[0].buf = buf; + -+ for (j = 0; j < cur_field->maxusage; j++) { -+ if (cur_field->usage[j].hid -+ == MS_TYPE_COVER_FEATURE_REPORT_USAGE) { -+ *field = cur_field; -+ return; -+ } -+ } -+ } ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].len = 1; ++ msg[1].buf = &buf[1]; ++ *val = 0; ++ ++ ret = i2c_transfer(client->adapter, msg, 2); ++ if (ret < 0) ++ return ret; ++ ++ *val = buf[1]; ++ ++ return 0; ++} ++ ++static int dw9719_i2c_wr8(struct i2c_client *client, u8 reg, u8 val) ++{ ++ struct i2c_msg msg; ++ int ret; ++ ++ u8 buf[2] = { reg, val }; ++ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ msg.len = sizeof(buf); ++ msg.buf = buf; ++ ++ ret = i2c_transfer(client->adapter, &msg, 1); ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int dw9719_i2c_wr16(struct i2c_client *client, u8 reg, u16 val) ++{ ++ struct i2c_msg msg; ++ u8 buf[3] = { reg }; ++ int ret; ++ ++ put_unaligned_be16(val, buf + 1); ++ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ msg.len = sizeof(buf); ++ msg.buf = buf; ++ ++ ret = i2c_transfer(client->adapter, &msg, 1); ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int dw9719_detect(struct dw9719_device *dw9719) ++{ ++ int ret; ++ u8 val; ++ ++ ret = dw9719_i2c_rd8(dw9719->client, DW9719_INFO, &val); ++ if (ret < 0) ++ return ret; ++ ++ if (val != DW9719_ID) { ++ dev_err(dw9719->dev, "Failed to detect correct id\n"); ++ ret = -ENXIO; + } ++ ++ return 0; +} + -+static void update_keyboard_backlight(struct hid_device *hdev, bool enabled) ++static int dw9719_power_down(struct dw9719_device *dw9719) +{ -+ struct usb_device *udev = hid_to_usb_dev(hdev); -+ struct hid_field *field = NULL; ++ return regulator_bulk_disable(NUM_REGULATORS, dw9719->regulators); ++} + -+ /* Wake up the device in case it's already suspended */ -+ pm_runtime_get_sync(&udev->dev); ++static int dw9719_power_up(struct dw9719_device *dw9719) ++{ ++ int ret; + -+ get_type_cover_backlight_field(hdev, &field); -+ if (!field) { -+ hid_err(hdev, "couldn't find backlight field\n"); -+ goto out; ++ ret = regulator_bulk_enable(NUM_REGULATORS, dw9719->regulators); ++ if (ret) ++ return ret; ++ ++ /* Jiggle SCL pin to wake up device */ ++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_CONTROL, 1); ++ ++ /* Need 100us to transit from SHUTDOWN to STANDBY*/ ++ usleep_range(100, 1000); ++ ++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_CONTROL, ++ DW9719_ENABLE_RINGING); ++ if (ret < 0) ++ goto fail_powerdown; ++ ++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_MODE, DW9719_MODE_SAC3); ++ if (ret < 0) ++ goto fail_powerdown; ++ ++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_VCM_FREQ, ++ DW9719_DEFAULT_VCM_FREQ); ++ if (ret < 0) ++ goto fail_powerdown; ++ ++ return 0; ++ ++fail_powerdown: ++ dw9719_power_down(dw9719); ++ return ret; ++} ++ ++static int dw9719_t_focus_abs(struct dw9719_device *dw9719, s32 value) ++{ ++ int ret; ++ ++ value = clamp(value, 0, DW9719_MAX_FOCUS_POS); ++ ret = dw9719_i2c_wr16(dw9719->client, DW9719_VCM_CURRENT, value); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int dw9719_set_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct dw9719_device *dw9719 = container_of(ctrl->handler, ++ struct dw9719_device, ++ ctrls.handler); ++ int ret; ++ ++ /* Only apply changes to the controls if the device is powered up */ ++ if (!pm_runtime_get_if_in_use(dw9719->dev)) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_FOCUS_ABSOLUTE: ++ ret = dw9719_t_focus_abs(dw9719, ctrl->val); ++ break; ++ default: ++ ret = -EINVAL; + } + -+ field->value[field->index] = enabled ? 0x01ff00ff : 0x00ff00ff; -+ hid_hw_request(hdev, field->report, HID_REQ_SET_REPORT); ++ pm_runtime_put(dw9719->dev); + -+out: -+ pm_runtime_put_sync(&udev->dev); ++ return ret; +} + -+static int mt_pm_notifier(struct notifier_block *notifier, -+ unsigned long pm_event, -+ void *unused) ++static const struct v4l2_ctrl_ops dw9719_ctrl_ops = { ++ .s_ctrl = dw9719_set_ctrl, ++}; ++ ++static int __maybe_unused dw9719_suspend(struct device *dev) +{ -+ struct mt_device *td = -+ container_of(notifier, struct mt_device, pm_notifier); -+ struct hid_device *hdev = td->hdev; ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct dw9719_device *dw9719 = to_dw9719_device(sd); ++ int ret; ++ int val; + -+ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT) { -+ if (pm_event == PM_SUSPEND_PREPARE) -+ update_keyboard_backlight(hdev, 0); -+ else if (pm_event == PM_POST_SUSPEND) -+ update_keyboard_backlight(hdev, 1); ++ for (val = dw9719->ctrls.focus->val; val >= 0; ++ val -= DW9719_CTRL_STEPS) { ++ ret = dw9719_t_focus_abs(dw9719, val); ++ if (ret) ++ return ret; ++ ++ usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10); ++ } ++ ++ return dw9719_power_down(dw9719); ++} ++ ++static int __maybe_unused dw9719_resume(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct dw9719_device *dw9719 = to_dw9719_device(sd); ++ int current_focus = dw9719->ctrls.focus->val; ++ int ret; ++ int val; ++ ++ ret = dw9719_power_up(dw9719); ++ if (ret) ++ return ret; ++ ++ for (val = current_focus % DW9719_CTRL_STEPS; val < current_focus; ++ val += DW9719_CTRL_STEPS) { ++ ret = dw9719_t_focus_abs(dw9719, val); ++ if (ret) ++ goto err_power_down; ++ ++ usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10); ++ } ++ ++ return 0; ++ ++err_power_down: ++ dw9719_power_down(dw9719); ++ return ret; ++} ++ ++static int dw9719_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ++{ ++ return pm_runtime_resume_and_get(sd->dev); ++} ++ ++static int dw9719_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ++{ ++ pm_runtime_put(sd->dev); ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_internal_ops dw9719_internal_ops = { ++ .open = dw9719_open, ++ .close = dw9719_close, ++}; ++ ++static int dw9719_init_controls(struct dw9719_device *dw9719) ++{ ++ const struct v4l2_ctrl_ops *ops = &dw9719_ctrl_ops; ++ int ret; ++ ++ ret = v4l2_ctrl_handler_init(&dw9719->ctrls.handler, 1); ++ if (ret) ++ return ret; ++ ++ dw9719->ctrls.focus = v4l2_ctrl_new_std(&dw9719->ctrls.handler, ops, ++ V4L2_CID_FOCUS_ABSOLUTE, 0, ++ DW9719_MAX_FOCUS_POS, 1, 0); ++ ++ if (dw9719->ctrls.handler.error) { ++ dev_err(dw9719->dev, "Error initialising v4l2 ctrls\n"); ++ ret = dw9719->ctrls.handler.error; ++ goto err_free_handler; + } + -+ return NOTIFY_DONE; ++ dw9719->sd.ctrl_handler = &dw9719->ctrls.handler; ++ ++ return ret; ++ ++err_free_handler: ++ v4l2_ctrl_handler_free(&dw9719->ctrls.handler); ++ return ret; ++} ++ ++static const struct v4l2_subdev_ops dw9719_ops = { }; ++ ++static int dw9719_probe(struct i2c_client *client) ++{ ++ struct dw9719_device *dw9719; ++ int ret; ++ ++ dw9719 = devm_kzalloc(&client->dev, sizeof(*dw9719), GFP_KERNEL); ++ if (!dw9719) ++ return -ENOMEM; ++ ++ dw9719->client = client; ++ dw9719->dev = &client->dev; ++ ++ dw9719->regulators[0].supply = "vdd"; ++ /* ++ * The DW9719 has only the 1 VDD voltage input, but some PMICs such as ++ * the TPS68470 PMIC have I2C passthrough capability, to disconnect the ++ * sensor's I2C pins from the I2C bus when the sensors VSIO (Sensor-IO) ++ * is off, because some sensors then short these pins to ground; ++ * and the DW9719 might sit behind this passthrough, this it needs to ++ * enable VSIO as that will also enable the I2C passthrough. ++ */ ++ dw9719->regulators[1].supply = "vsio"; ++ ++ ret = devm_regulator_bulk_get(&client->dev, NUM_REGULATORS, ++ dw9719->regulators); ++ if (ret) ++ return dev_err_probe(&client->dev, ret, "getting regulators\n"); ++ ++ v4l2_i2c_subdev_init(&dw9719->sd, client, &dw9719_ops); ++ dw9719->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ dw9719->sd.internal_ops = &dw9719_internal_ops; ++ ++ ret = dw9719_init_controls(dw9719); ++ if (ret) ++ return ret; ++ ++ ret = media_entity_pads_init(&dw9719->sd.entity, 0, NULL); ++ if (ret < 0) ++ goto err_free_ctrl_handler; ++ ++ dw9719->sd.entity.function = MEDIA_ENT_F_LENS; ++ ++ /* ++ * We need the driver to work in the event that pm runtime is disable in ++ * the kernel, so power up and verify the chip now. In the event that ++ * runtime pm is disabled this will leave the chip on, so that the lens ++ * will work. ++ */ ++ ++ ret = dw9719_power_up(dw9719); ++ if (ret) ++ goto err_cleanup_media; ++ ++ ret = dw9719_detect(dw9719); ++ if (ret) ++ goto err_powerdown; ++ ++ pm_runtime_set_active(&client->dev); ++ pm_runtime_get_noresume(&client->dev); ++ pm_runtime_enable(&client->dev); ++ ++ ret = v4l2_async_register_subdev(&dw9719->sd); ++ if (ret < 0) ++ goto err_pm_runtime; ++ ++ pm_runtime_set_autosuspend_delay(&client->dev, 1000); ++ pm_runtime_use_autosuspend(&client->dev); ++ pm_runtime_put_autosuspend(&client->dev); ++ ++ return ret; ++ ++err_pm_runtime: ++ pm_runtime_disable(&client->dev); ++ pm_runtime_put_noidle(&client->dev); ++err_powerdown: ++ dw9719_power_down(dw9719); ++err_cleanup_media: ++ media_entity_cleanup(&dw9719->sd.entity); ++err_free_ctrl_handler: ++ v4l2_ctrl_handler_free(&dw9719->ctrls.handler); ++ ++ return ret; ++} ++ ++static int dw9719_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct dw9719_device *dw9719 = container_of(sd, struct dw9719_device, ++ sd); ++ ++ pm_runtime_disable(&client->dev); ++ v4l2_async_unregister_subdev(sd); ++ v4l2_ctrl_handler_free(&dw9719->ctrls.handler); ++ media_entity_cleanup(&dw9719->sd.entity); ++ ++ return 0; +} + - static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) - { - int ret, i; -@@ -1718,6 +1801,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) - td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; - hid_set_drvdata(hdev, td); - -+ td->pm_notifier.notifier_call = mt_pm_notifier; -+ register_pm_notifier(&td->pm_notifier); ++static const struct i2c_device_id dw9719_id_table[] = { ++ { "dw9719" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, dw9719_id_table); + - INIT_LIST_HEAD(&td->applications); - INIT_LIST_HEAD(&td->reports); - -@@ -1747,15 +1833,19 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) - timer_setup(&td->release_timer, mt_expired_timeout, 0); - - ret = hid_parse(hdev); -- if (ret != 0) -+ if (ret != 0) { -+ unregister_pm_notifier(&td->pm_notifier); - return ret; -+ } ++static const struct dev_pm_ops dw9719_pm_ops = { ++ SET_RUNTIME_PM_OPS(dw9719_suspend, dw9719_resume, NULL) ++}; ++ ++static struct i2c_driver dw9719_i2c_driver = { ++ .driver = { ++ .name = "dw9719", ++ .pm = &dw9719_pm_ops, ++ }, ++ .probe_new = dw9719_probe, ++ .remove = dw9719_remove, ++ .id_table = dw9719_id_table, ++}; ++module_i2c_driver(dw9719_i2c_driver); ++ ++MODULE_AUTHOR("Daniel Scally "); ++MODULE_DESCRIPTION("DW9719 VCM Driver"); ++MODULE_LICENSE("GPL"); +-- +2.36.1 + +From 49bf34135d89166093cfea5f817e5ac6862b0ccf Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Mon, 13 Dec 2021 22:38:17 +0000 +Subject: [PATCH] media: entity: Skip non-data links in graph iteration + +When iterating over the media graph, don't follow links that are not +data links. + +Reviewed-by: Laurent Pinchart +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/media/mc/mc-entity.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c +index b411f9796191..d0563ee4b28b 100644 +--- a/drivers/media/mc/mc-entity.c ++++ b/drivers/media/mc/mc-entity.c +@@ -295,6 +295,12 @@ static void media_graph_walk_iter(struct media_graph *graph) - if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID) - mt_fix_const_fields(hdev, HID_DG_CONTACTID); + link = list_entry(link_top(graph), typeof(*link), list); - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); -- if (ret) -+ if (ret) { -+ unregister_pm_notifier(&td->pm_notifier); - return ret; ++ /* If the link is not a data link, don't follow it */ ++ if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) { ++ link_top(graph) = link_top(graph)->next; ++ return; + } - - ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); - if (ret) -@@ -1807,6 +1897,7 @@ static void mt_remove(struct hid_device *hdev) - { - struct mt_device *td = hid_get_drvdata(hdev); - -+ unregister_pm_notifier(&td->pm_notifier); - del_timer_sync(&td->release_timer); - - sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); -@@ -2174,6 +2265,11 @@ static const struct hid_device_id mt_devices[] = { - MT_USB_DEVICE(USB_VENDOR_ID_XIROKU, - USB_DEVICE_ID_XIROKU_CSR2) }, - -+ /* Microsoft Surface type cover */ -+ { .driver_data = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER, -+ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, -+ USB_VENDOR_ID_MICROSOFT, 0x09c0) }, + - /* Google MT devices */ - { .driver_data = MT_CLS_GOOGLE, - HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE, + /* The link is not enabled so we do not follow. */ + if (!(link->flags & MEDIA_LNK_FL_ENABLED)) { + link_top(graph) = link_top(graph)->next; -- -2.36.0 - -From 48eab1c5e0d9fe67384d6c2e91efdf0ec3ff54b5 Mon Sep 17 00:00:00 2001 -From: Maximilian Luz -Date: Tue, 8 Feb 2022 01:29:48 +0100 -Subject: [PATCH] ACPI: battery: Add "Not Charging" quirk for Microsoft Surface - devices +2.36.1 -Microsoft Surface devices have a limiter that sets a fixed maximum -charge capacity for the battery. When that maximum capacity has been -reached, charging stops. In that case, _BST returns a battery state -field with both "charging" and "discharging" bits cleared. The battery -driver, however, returns "unknown" as status. +From 84e122d9c2fa461ce17b61989b5676c695a07fba Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Mon, 13 Dec 2021 22:53:09 +0000 +Subject: [PATCH] media: media.h: Add new media link type -This seems to be the same behavior as observed on the ThinkPads, so -let's use the same quirk to handle that as well. +To describe in the kernel the connection between devices and their +supporting peripherals (for example, a camera sensor and the vcm +driving the focusing lens for it), add a new type of media link +to introduce the concept of these ancillary links. -Signed-off-by: Maximilian Luz -Patchset: surface-battery +Add some elements to the uAPI documentation to explain the new link +type, their purpose and some aspects of their current implementation. +Reviewed-by: Laurent Pinchart +Signed-off-by: Daniel Scally +Patchset: cameras --- -For what it's worth, I don't think the ACPI spec explicitly states that -any of the status bits need to be set, or that there are only the -"charging" and "discharging" states. As far as I can tell, ACPI only -states: - - Notice that the Charging bit and the Discharging bit are mutually - exclusive and must not both be set at the same time. Even in - critical state, hardware should report the corresponding - charging/discharging state. - -But that does not exclude the case that no bit is set. So, strictly -going by spec, I don't think it's necessary to put all of this behind a -quirk. ---- - drivers/acpi/battery.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c -index dc208f5f5a1f..db2aa56c746a 100644 ---- a/drivers/acpi/battery.c -+++ b/drivers/acpi/battery.c -@@ -1152,6 +1152,14 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"), - }, - }, -+ { -+ .callback = battery_quirk_not_charging, -+ .ident = "Microsoft Surface", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Surface"), -+ }, -+ }, - { - /* Microsoft Surface Go 3 */ - .callback = battery_notification_delay_quirk, + .../media/mediactl/media-controller-model.rst | 6 ++++++ + .../media/mediactl/media-types.rst | 17 ++++++++++++----- + include/uapi/linux/media.h | 1 + + 3 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/Documentation/userspace-api/media/mediactl/media-controller-model.rst b/Documentation/userspace-api/media/mediactl/media-controller-model.rst +index 222cb99debb5..78bfdfb2a322 100644 +--- a/Documentation/userspace-api/media/mediactl/media-controller-model.rst ++++ b/Documentation/userspace-api/media/mediactl/media-controller-model.rst +@@ -33,3 +33,9 @@ are: + + - An **interface link** is a point-to-point bidirectional control + connection between a Linux Kernel interface and an entity. ++ ++- An **ancillary link** is a point-to-point connection denoting that two ++ entities form a single logical unit. For example this could represent the ++ fact that a particular camera sensor and lens controller form a single ++ physical module, meaning this lens controller drives the lens for this ++ camera sensor. +\ No newline at end of file +diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst +index 0a26397bd01d..60747251d409 100644 +--- a/Documentation/userspace-api/media/mediactl/media-types.rst ++++ b/Documentation/userspace-api/media/mediactl/media-types.rst +@@ -412,14 +412,21 @@ must be set for every pad. + is set by drivers and is read-only for applications. + + * - ``MEDIA_LNK_FL_LINK_TYPE`` +- - This is a bitmask that defines the type of the link. Currently, +- two types of links are supported: ++ - This is a bitmask that defines the type of the link. The following ++ link types are currently supported: + + .. _MEDIA-LNK-FL-DATA-LINK: + +- ``MEDIA_LNK_FL_DATA_LINK`` if the link is between two pads ++ ``MEDIA_LNK_FL_DATA_LINK`` for links that represent a data connection ++ between two pads. + + .. _MEDIA-LNK-FL-INTERFACE-LINK: + +- ``MEDIA_LNK_FL_INTERFACE_LINK`` if the link is between an +- interface and an entity ++ ``MEDIA_LNK_FL_INTERFACE_LINK`` for links that associate an entity to its ++ interface. ++ ++ .. _MEDIA-LNK-FL-ANCILLARY-LINK: ++ ++ ``MEDIA_LNK_FL_ANCILLARY_LINK`` for links that represent a physical ++ relationship between two entities. The link may or may not be ummutable, so ++ applications must not assume either case. +\ No newline at end of file +diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h +index 200fa8462b90..afbae7213d35 100644 +--- a/include/uapi/linux/media.h ++++ b/include/uapi/linux/media.h +@@ -226,6 +226,7 @@ struct media_pad_desc { + #define MEDIA_LNK_FL_LINK_TYPE (0xf << 28) + # define MEDIA_LNK_FL_DATA_LINK (0 << 28) + # define MEDIA_LNK_FL_INTERFACE_LINK (1 << 28) ++# define MEDIA_LNK_FL_ANCILLARY_LINK (2 << 28) + + struct media_link_desc { + struct media_pad_desc source; -- -2.36.0 - -From f31a3ad42c2c04a17f8675438a1b5a6500bafea5 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sun, 10 Oct 2021 20:56:57 +0200 -Subject: [PATCH] ACPI: delay enumeration of devices with a _DEP pointing to an - INT3472 device +2.36.1 -The clk and regulator frameworks expect clk/regulator consumer-devices -to have info about the consumed clks/regulators described in the device's -fw_node. +From b9085eecf59dc89d1b82337697e455b31cdd4e1c Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Mon, 13 Dec 2021 22:36:31 +0000 +Subject: [PATCH] media: entity: Add link_type_name() helper -To work around cases where this info is not present in the firmware tables, -which is often the case on x86/ACPI devices, both frameworks allow the -provider-driver to attach info about consumers to the clks/regulators -when registering these. +Now we have three types of media link, printing the right name during +debug output is slightly more complicated. Add a helper function to +make it easier. -This causes problems with the probe ordering wrt drivers for consumers -of these clks/regulators. Since the lookups are only registered when the -provider-driver binds, trying to get these clks/regulators before then -results in a -ENOENT error for clks and a dummy regulator for regulators. +Reviewed-by: Laurent Pinchart +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/media/mc/mc-entity.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c +index d0563ee4b28b..1a7d0a4fb9e8 100644 +--- a/drivers/media/mc/mc-entity.c ++++ b/drivers/media/mc/mc-entity.c +@@ -44,6 +44,20 @@ static inline const char *intf_type(struct media_interface *intf) + } + }; + ++static inline const char *link_type_name(struct media_link *link) ++{ ++ switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) { ++ case MEDIA_LNK_FL_DATA_LINK: ++ return "data"; ++ case MEDIA_LNK_FL_INTERFACE_LINK: ++ return "interface"; ++ case MEDIA_LNK_FL_ANCILLARY_LINK: ++ return "ancillary"; ++ default: ++ return "unknown"; ++ } ++} ++ + __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum, + int idx_max) + { +@@ -89,9 +103,7 @@ static void dev_dbg_obj(const char *event_name, struct media_gobj *gobj) + + dev_dbg(gobj->mdev->dev, + "%s id %u: %s link id %u ==> id %u\n", +- event_name, media_id(gobj), +- media_type(link->gobj0) == MEDIA_GRAPH_PAD ? +- "data" : "interface", ++ event_name, media_id(gobj), link_type_name(link), + media_id(link->gobj0), + media_id(link->gobj1)); + break; +-- +2.36.1 -One case where we hit this issue is camera sensors such as e.g. the OV8865 -sensor found on the Microsoft Surface Go. The sensor uses clks, regulators -and GPIOs provided by a TPS68470 PMIC which is described in an INT3472 -ACPI device. There is special platform code handling this and setting -platform_data with the necessary consumer info on the MFD cells -instantiated for the PMIC under: drivers/platform/x86/intel/int3472. +From 6f6547dac5f877a7c07c0f947167d3af109888fb Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Mon, 13 Dec 2021 22:54:10 +0000 +Subject: [PATCH] media: entity: Add support for ancillary links -For this to work properly the ov8865 driver must not bind to the I2C-client -for the OV8865 sensor until after the TPS68470 PMIC gpio, regulator and -clk MFD cells have all been fully setup. +Add functions to create ancillary links, so that they don't need to +be manually created by users. -The OV8865 on the Microsoft Surface Go is just one example, all X86 -devices using the Intel IPU3 camera block found on recent Intel SoCs -have similar issues where there is an INT3472 HID ACPI-device, which -describes the clks and regulators, and the driver for this INT3472 device -must be fully initialized before the sensor driver (any sensor driver) -binds for things to work properly. +Reviewed-by: Laurent Pinchart +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/media/mc/mc-entity.c | 22 ++++++++++++++++++++++ + include/media/media-entity.h | 19 +++++++++++++++++++ + 2 files changed, 41 insertions(+) + +diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c +index 1a7d0a4fb9e8..d7e2f78a83cc 100644 +--- a/drivers/media/mc/mc-entity.c ++++ b/drivers/media/mc/mc-entity.c +@@ -1032,3 +1032,25 @@ void media_remove_intf_links(struct media_interface *intf) + mutex_unlock(&mdev->graph_mutex); + } + EXPORT_SYMBOL_GPL(media_remove_intf_links); ++ ++struct media_link *media_create_ancillary_link(struct media_entity *primary, ++ struct media_entity *ancillary) ++{ ++ struct media_link *link; ++ ++ link = media_add_link(&primary->links); ++ if (!link) ++ return ERR_PTR(-ENOMEM); ++ ++ link->gobj0 = &primary->graph_obj; ++ link->gobj1 = &ancillary->graph_obj; ++ link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED | ++ MEDIA_LNK_FL_ANCILLARY_LINK; ++ ++ /* Initialize graph object embedded in the new link */ ++ media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK, ++ &link->graph_obj); ++ ++ return link; ++} ++EXPORT_SYMBOL_GPL(media_create_ancillary_link); +diff --git a/include/media/media-entity.h b/include/media/media-entity.h +index fea489f03d57..2a58defc4886 100644 +--- a/include/media/media-entity.h ++++ b/include/media/media-entity.h +@@ -1108,4 +1108,23 @@ void media_remove_intf_links(struct media_interface *intf); + (((entity)->ops && (entity)->ops->operation) ? \ + (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD) + ++/** ++ * media_create_ancillary_link() - create an ancillary link between two ++ * instances of &media_entity ++ * ++ * @primary: pointer to the primary &media_entity ++ * @ancillary: pointer to the ancillary &media_entity ++ * ++ * Create an ancillary link between two entities, indicating that they ++ * represent two connected pieces of hardware that form a single logical unit. ++ * A typical example is a camera lens controller being linked to the sensor that ++ * it is supporting. ++ * ++ * The function sets both MEDIA_LNK_FL_ENABLED and MEDIA_LNK_FL_IMMUTABLE for ++ * the new link. ++ */ ++struct media_link * ++media_create_ancillary_link(struct media_entity *primary, ++ struct media_entity *ancillary); ++ + #endif +-- +2.36.1 -On these devices the ACPI nodes describing the sensors all have a _DEP -dependency on the matching INT3472 ACPI device (there is one per sensor). +From eb85a0a2c18d5596e996322286ffb1bcc326443c Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Fri, 26 Nov 2021 22:55:50 +0000 +Subject: [PATCH] media: v4l2-async: Create links during + v4l2_async_match_notify() -This allows solving the probe-ordering problem by delaying the enumeration -(instantiation of the I2C-client in the ov8865 example) of ACPI-devices -which have a _DEP dependency on an INT3472 device. +Upon an async fwnode match, there's some typical behaviour that the +notifier and matching subdev will want to do. For example, a notifier +representing a sensor matching to an async subdev representing its +VCM will want to create an ancillary link to expose that relationship +to userspace. -The new acpi_dev_ready_for_enumeration() helper used for this is also -exported because for devices, which have the enumeration_by_parent flag -set, the parent-driver will do its own scan of child ACPI devices and -it will try to enumerate those during its probe(). Code doing this such -as e.g. the i2c-core-acpi.c code must call this new helper to ensure -that it too delays the enumeration until all the _DEP dependencies are -met on devices which have the new honor_deps flag set. +To avoid lots of code in individual drivers, try to build these links +within v4l2 core. -Signed-off-by: Hans de Goede +Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/acpi/scan.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c -index c82b1bfa1c3d..2227625202aa 100644 ---- a/drivers/acpi/scan.c -+++ b/drivers/acpi/scan.c -@@ -2130,6 +2130,9 @@ static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used, + drivers/media/v4l2-core/v4l2-async.c | 31 ++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c +index 0404267f1ae4..436bd6900fd8 100644 +--- a/drivers/media/v4l2-core/v4l2-async.c ++++ b/drivers/media/v4l2-core/v4l2-async.c +@@ -275,6 +275,24 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier) + static int + v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier); + ++static int v4l2_async_create_ancillary_links(struct v4l2_async_notifier *n, ++ struct v4l2_subdev *sd) ++{ ++ struct media_link *link = NULL; ++ ++#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) ++ ++ if (sd->entity.function != MEDIA_ENT_F_LENS && ++ sd->entity.function != MEDIA_ENT_F_FLASH) ++ return 0; ++ ++ link = media_create_ancillary_link(&n->sd->entity, &sd->entity); ++ ++#endif ++ ++ return IS_ERR(link) ? PTR_ERR(link) : 0; ++} ++ + static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, + struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd, +@@ -293,6 +311,19 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, + return ret; + } - static void acpi_default_enumeration(struct acpi_device *device) - { -+ if (!acpi_dev_ready_for_enumeration(device)) -+ return; ++ /* ++ * Depending of the function of the entities involved, we may want to ++ * create links between them (for example between a sensor and its lens ++ * or between a sensor's source pad and the connected device's sink ++ * pad). ++ */ ++ ret = v4l2_async_create_ancillary_links(notifier, sd); ++ if (ret) { ++ v4l2_async_nf_call_unbind(notifier, sd, asd); ++ v4l2_device_unregister_subdev(sd); ++ return ret; ++ } + - /* - * Do not enumerate devices with enumeration_by_parent flag set as - * they will be enumerated by their respective parents. + /* Remove from the waiting list */ + list_del(&asd->list); + sd->asd = asd; -- -2.36.0 +2.36.1 -From 3f7aa178a14b5cdaa3ca424743299d0c271fd202 Mon Sep 17 00:00:00 2001 +From 613f354f08b44f7e0909c7ffde8f9ce69c81acc8 Mon Sep 17 00:00:00 2001 From: Daniel Scally -Date: Sun, 10 Oct 2021 20:57:02 +0200 -Subject: [PATCH] platform/x86: int3472: Enable I2c daisy chain +Date: Wed, 4 May 2022 23:21:45 +0100 +Subject: [PATCH] media: ipu3-cio2: Move functionality from .complete() to + .bound() -The TPS68470 PMIC has an I2C passthrough mode through which I2C traffic -can be forwarded to a device connected to the PMIC as though it were -connected directly to the system bus. Enable this mode when the chip -is initialised. +Creating links and registering subdev nodes during the .complete() +callback has the unfortunate effect of preventing all cameras that +connect to a notifier from working if any one of their drivers fails +to probe. Moving the functionality from .complete() to .bound() allows +those camera sensor drivers that did probe correctly to work regardless. Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/platform/x86/intel/int3472/tps68470.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c -index 22f61b47f9e5..e1de1ff40bba 100644 ---- a/drivers/platform/x86/intel/int3472/tps68470.c -+++ b/drivers/platform/x86/intel/int3472/tps68470.c -@@ -45,6 +45,13 @@ static int tps68470_chip_init(struct device *dev, struct regmap *regmap) - return ret; - } + drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 65 +++++++------------ + 1 file changed, 23 insertions(+), 42 deletions(-) + +diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +index 0e9b0503b62a..50682a7b2a07 100644 +--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c ++++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +@@ -1382,7 +1382,10 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, + { + struct cio2_device *cio2 = to_cio2_device(notifier); + struct sensor_async_subdev *s_asd = to_sensor_asd(asd); ++ struct device *dev = &cio2->pci_dev->dev; + struct cio2_queue *q; ++ unsigned int pad; ++ int ret; -+ /* Enable I2C daisy chain */ -+ ret = regmap_write(regmap, TPS68470_REG_S_I2C_CTL, 0x03); + if (cio2->queue[s_asd->csi2.port].sensor) + return -EBUSY; +@@ -1393,7 +1396,26 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, + q->sensor = sd; + q->csi_rx_base = cio2->base + CIO2_REG_PIPE_BASE(q->csi2.port); + +- return 0; ++ for (pad = 0; pad < q->sensor->entity.num_pads; pad++) ++ if (q->sensor->entity.pads[pad].flags & ++ MEDIA_PAD_FL_SOURCE) ++ break; ++ ++ if (pad == q->sensor->entity.num_pads) { ++ dev_err(dev, "failed to find src pad for %s\n", ++ q->sensor->name); ++ return -ENXIO; ++ } ++ ++ ret = media_create_pad_link(&q->sensor->entity, pad, &q->subdev.entity, ++ CIO2_PAD_SINK, 0); + if (ret) { -+ dev_err(dev, "Failed to enable i2c daisy chain\n"); ++ dev_err(dev, "failed to create link for %s\n", ++ q->sensor->name); + return ret; + } + - dev_info(dev, "TPS68470 REVID: 0x%02x\n", version); ++ return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev); + } - return 0; + /* The .unbind callback */ +@@ -1407,50 +1429,9 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier, + cio2->queue[s_asd->csi2.port].sensor = NULL; + } + +-/* .complete() is called after all subdevices have been located */ +-static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) +-{ +- struct cio2_device *cio2 = to_cio2_device(notifier); +- struct device *dev = &cio2->pci_dev->dev; +- struct sensor_async_subdev *s_asd; +- struct v4l2_async_subdev *asd; +- struct cio2_queue *q; +- unsigned int pad; +- int ret; +- +- list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) { +- s_asd = to_sensor_asd(asd); +- q = &cio2->queue[s_asd->csi2.port]; +- +- for (pad = 0; pad < q->sensor->entity.num_pads; pad++) +- if (q->sensor->entity.pads[pad].flags & +- MEDIA_PAD_FL_SOURCE) +- break; +- +- if (pad == q->sensor->entity.num_pads) { +- dev_err(dev, "failed to find src pad for %s\n", +- q->sensor->name); +- return -ENXIO; +- } +- +- ret = media_create_pad_link( +- &q->sensor->entity, pad, +- &q->subdev.entity, CIO2_PAD_SINK, +- 0); +- if (ret) { +- dev_err(dev, "failed to create link for %s\n", +- q->sensor->name); +- return ret; +- } +- } +- +- return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev); +-} +- + static const struct v4l2_async_notifier_operations cio2_async_ops = { + .bound = cio2_notifier_bound, + .unbind = cio2_notifier_unbind, +- .complete = cio2_notifier_complete, + }; + + static int cio2_parse_firmware(struct cio2_device *cio2) -- -2.36.0 +2.36.1 -From 2bd2d24b1a9f413760ef333262833def4c4c7ab2 Mon Sep 17 00:00:00 2001 +From cdc9fb2f64ebffa0f587d9dcebb5070703a784a3 Mon Sep 17 00:00:00 2001 From: Sachi King Date: Sat, 29 May 2021 17:47:38 +1000 Subject: [PATCH] ACPI: Add quirk for Surface Laptop 4 AMD missing irq 7 @@ -5528,9 +8673,9 @@ index 0d01e7f5078c..2b06cf5f2b1f 100644 mp_config_acpi_legacy_irqs(); -- -2.36.0 +2.36.1 -From 4413582ad25091f1ff7c163c97f938550430834a Mon Sep 17 00:00:00 2001 +From fceaab89173a0d9d3e55d3b90e06c15ca4f04cc7 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Thu, 3 Jun 2021 14:04:26 +0200 Subject: [PATCH] ACPI: Add AMD 13" Surface Laptop 4 model to irq 7 override @@ -5570,5 +8715,5 @@ index 2b06cf5f2b1f..caaec200bea2 100644 }; -- -2.36.0 +2.36.1 diff --git a/SOURCES/patch-5.17-redhat.patch b/SOURCES/patch-5.17-redhat.patch index 42a316d..187a9f9 100644 --- a/SOURCES/patch-5.17-redhat.patch +++ b/SOURCES/patch-5.17-redhat.patch @@ -24,6 +24,7 @@ drivers/firmware/efi/libstub/efistub.h | 74 ++++++++++++ drivers/firmware/efi/libstub/x86-stub.c | 119 +++++++++++++++++++- drivers/firmware/efi/secureboot.c | 38 +++++++ + drivers/firmware/sysfb.c | 18 ++- drivers/gpu/drm/i915/display/intel_bios.c | 6 + drivers/gpu/drm/i915/display/intel_psr.c | 9 ++ drivers/gpu/drm/i915/display/intel_vbt_defs.h | 3 + @@ -59,7 +60,7 @@ security/lockdown/Kconfig | 13 +++ security/lockdown/lockdown.c | 1 + security/security.c | 6 + - 61 files changed, 980 insertions(+), 212 deletions(-) + 62 files changed, 997 insertions(+), 213 deletions(-) diff --git a/Documentation/core-api/dma-attributes.rst b/Documentation/core-api/dma-attributes.rst index 1887d92e8e92..17706dc91ec9 100644 @@ -111,7 +112,7 @@ index 000000000000..733a26bd887a + +endmenu diff --git a/Makefile b/Makefile -index aba139bbd1c7..01a8c0b291ac 100644 +index b821f270a4ca..72a7c6958ea5 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,10 @@ $(if $(filter __%, $(MAKECMDGOALS)), \ @@ -1249,6 +1250,42 @@ index 000000000000..de0a3714a5d4 + } + } +} +diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c +index 2bfbb05f7d89..a504f7234f35 100644 +--- a/drivers/firmware/sysfb.c ++++ b/drivers/firmware/sysfb.c +@@ -34,6 +34,22 @@ + #include + #include + ++static int skip_simpledrm; ++ ++static int __init simpledrm_disable(char *opt) ++{ ++ if (!opt) ++ return -EINVAL; ++ ++ get_option(&opt, &skip_simpledrm); ++ ++ if (skip_simpledrm) ++ pr_info("The simpledrm driver will not be probed\n"); ++ ++ return 0; ++} ++early_param("nvidia-drm.modeset", simpledrm_disable); ++ + static __init int sysfb_init(void) + { + struct screen_info *si = &screen_info; +@@ -45,7 +61,7 @@ static __init int sysfb_init(void) + + /* try to create a simple-framebuffer device */ + compatible = sysfb_parse_mode(si, &mode); +- if (compatible) { ++ if (compatible && !skip_simpledrm) { + ret = sysfb_create_simplefb(si, &mode); + if (!ret) + return 0; diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 9d989c9f5da4..5d97a251d3dc 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c @@ -1684,7 +1721,7 @@ index 107dcf5938d6..225a9797e39d 100644 * Changes the default domain of an iommu group that has *only* one device * diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c -index 10f7c79caac2..8ac0161d2aef 100644 +index 0abd772c57f0..3c9889ce56ac 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -244,6 +244,9 @@ static void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl) @@ -1751,7 +1788,7 @@ index 10f7c79caac2..8ac0161d2aef 100644 } EXPORT_SYMBOL_GPL(nvme_complete_rq); diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c -index a703f1f5fb64..d77c24333cb4 100644 +index 189175fff7e4..c0627a9d1274 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -101,14 +101,10 @@ bool nvme_mpath_set_disk_name(struct nvme_ns *ns, char *disk_name, int *flags) @@ -1787,7 +1824,7 @@ index a703f1f5fb64..d77c24333cb4 100644 spin_lock_irqsave(&ns->head->requeue_lock, flags); for (bio = req->bio; bio; bio = bio->bi_next) { -@@ -870,8 +876,7 @@ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) +@@ -891,8 +897,7 @@ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) int error = 0; /* check if multipath is enabled and we have the capability */ @@ -1798,7 +1835,7 @@ index a703f1f5fb64..d77c24333cb4 100644 if (!ctrl->max_namespaces || diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h -index 68c42e831117..6a7091335257 100644 +index 85f3f55c71c5..aad43c21c0a4 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -794,6 +794,7 @@ void nvme_mpath_start_freeze(struct nvme_subsystem *subsys); @@ -1809,7 +1846,7 @@ index 68c42e831117..6a7091335257 100644 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl); int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head); void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id); -@@ -832,6 +833,9 @@ static inline bool nvme_mpath_set_disk_name(struct nvme_ns *ns, char *disk_name, +@@ -833,6 +834,9 @@ static inline bool nvme_mpath_set_disk_name(struct nvme_ns *ns, char *disk_name, static inline void nvme_failover_req(struct request *req) { } @@ -2144,10 +2181,10 @@ index ab7eea01ab42..fff7c5f737fc 100644 int rmi_register_transport_device(struct rmi_transport_dev *xport); diff --git a/include/linux/security.h b/include/linux/security.h -index 25b3ef71f495..d37a6c88c69f 100644 +index 7fc4e9f49f54..6f0b0b2dc73d 100644 --- a/include/linux/security.h +++ b/include/linux/security.h -@@ -471,6 +471,7 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); +@@ -473,6 +473,7 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_locked_down(enum lockdown_reason what); @@ -2155,7 +2192,7 @@ index 25b3ef71f495..d37a6c88c69f 100644 #else /* CONFIG_SECURITY */ static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) -@@ -1347,6 +1348,10 @@ static inline int security_locked_down(enum lockdown_reason what) +@@ -1349,6 +1350,10 @@ static inline int security_locked_down(enum lockdown_reason what) { return 0; } @@ -2365,10 +2402,10 @@ index 87cbdc64d272..18555cf18da7 100644 static int __init lockdown_lsm_init(void) diff --git a/security/security.c b/security/security.c -index b7cf5cbfdc67..3cde9062fcf6 100644 +index aaf6566deb9f..86926966c15d 100644 --- a/security/security.c +++ b/security/security.c -@@ -2623,6 +2623,12 @@ int security_locked_down(enum lockdown_reason what) +@@ -2625,6 +2625,12 @@ int security_locked_down(enum lockdown_reason what) } EXPORT_SYMBOL(security_locked_down); diff --git a/SOURCES/simpledrm-nvidia.patch b/SOURCES/simpledrm-nvidia.patch deleted file mode 100644 index 48be3c8..0000000 --- a/SOURCES/simpledrm-nvidia.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 205bec68a0ea67b6bff6fea9603b7b8aeacc9d46 Mon Sep 17 00:00:00 2001 -From: Javier Martinez Canillas -Date: Thu, 19 May 2022 14:40:07 +0200 -Subject: [PATCH 1/2] drivers/firmware: skip simpledrm if nvidia-drm.modeset=1 - is set - -The Nvidia proprietary driver has some bugs that leads to issues if used -with the simpledrm driver. The most noticeable is that does not register -an emulated fbdev device. - -It just relies on a fbdev to be registered by another driver, that could -be that could be attached to the framebuffer console. On UEFI machines, -this is the efifb driver. - -This means that disabling the efifb driver will cause virtual consoles to -not be present in the system when using the Nvidia driver. Legacy BIOS is -not affected just because fbcon is not used there, but instead vgacon. - -Unless a VGA mode is specified using the vga= kernel command line option, -in that case the vesafb driver is used instead and its fbdev attached to -the fbcon. - -This is a problem because with CONFIG_SYSFB_SIMPLEFB=y, the sysfb platform -code attempts to register a "simple-framebuffer" platform device (that is -matched against simpledrm) and only registers either an "efi-framebuffer" -or "vesa-framebuffer" if this fails to be registered due the video modes -not being compatible. - -The Nvidia driver relying on another driver to register the fbdev is quite -fragile, since it can't really assume those will stick around. For example -there are patches posted to remove the EFI and VESA platform devices once -a real DRM or fbdev driver probes. - -But in any case, moving to a simpledrm + emulated fbdev only breaks this -assumption and causes users to not have VT if the Nvidia driver is used. - -So to prevent this, let's add a workaround and make the sysfb to skip the -"simple-framebuffer" registration when nvidia-drm.modeset=1 option is set. - -This is quite horrible, but honestly I can't think of any other approach. - -For this to work, the CONFIG_FB_EFI and CONFIG_FB_VESA config options must -be enabled besides CONFIG_DRM_SIMPLEDRM. - -Signed-off-by: Javier Martinez Canillas ---- - drivers/firmware/sysfb.c | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c -index 2bfbb05f7d89..a504f7234f35 100644 ---- a/drivers/firmware/sysfb.c -+++ b/drivers/firmware/sysfb.c -@@ -34,6 +34,22 @@ - #include - #include - -+static int skip_simpledrm; -+ -+static int __init simpledrm_disable(char *opt) -+{ -+ if (!opt) -+ return -EINVAL; -+ -+ get_option(&opt, &skip_simpledrm); -+ -+ if (skip_simpledrm) -+ pr_info("The simpledrm driver will not be probed\n"); -+ -+ return 0; -+} -+early_param("nvidia-drm.modeset", simpledrm_disable); -+ - static __init int sysfb_init(void) - { - struct screen_info *si = &screen_info; -@@ -45,7 +61,7 @@ static __init int sysfb_init(void) - - /* try to create a simple-framebuffer device */ - compatible = sysfb_parse_mode(si, &mode); -- if (compatible) { -+ if (compatible && !skip_simpledrm) { - ret = sysfb_create_simplefb(si, &mode); - if (!ret) - return 0; --- -GitLab diff --git a/SPECS/kernel.spec b/SPECS/kernel.spec index 202fd71..1a63f5a 100755 --- a/SPECS/kernel.spec +++ b/SPECS/kernel.spec @@ -130,15 +130,15 @@ Summary: The Linux kernel # The kernel tarball/base version %define kversion 5.17 -%define rpmversion 5.17.9 +%define rpmversion 5.17.11 %define patchversion 5.17 -%define pkgrelease 302 +%define pkgrelease 301 # This is needed to do merge window version magic %define patchlevel 17 # allow pkg_release to have configurable %%{?dist} tag -%define specrelease 302%{?buildid}%{?dist} +%define specrelease 301%{?buildid}%{?dist} %define pkg_release %{specrelease} @@ -695,7 +695,7 @@ BuildRequires: lld # exact git commit you can run # # xzcat -qq ${TARBALL} | git get-tar-commit-id -Source0: linux-5.17.9.tar.xz +Source0: linux-5.17.11.tar.xz Source1: Makefile.rhelver @@ -869,8 +869,6 @@ Patch300: linux-surface.patch Patch301: steam-deck.patch # temporary patches -# https://gitlab.com/cki-project/kernel-ark/-/merge_requests/1788 -Patch501: simpledrm-nvidia.patch # https://gitlab.freedesktop.org/drm/amd/-/issues/1925 Patch502: 0001-drm-amd-pm-correct-the-metrics-version-for-SMU-11.0..patch %endif @@ -1403,8 +1401,8 @@ ApplyOptionalPatch() fi } -%setup -q -n kernel-5.17.9 -c -mv linux-5.17.9 linux-%{KVERREL} +%setup -q -n kernel-5.17.11 -c +mv linux-5.17.11 linux-%{KVERREL} cd linux-%{KVERREL} cp -a %{SOURCE1} . @@ -1424,7 +1422,7 @@ ApplyOptionalPatch linux-surface.patch ApplyOptionalPatch steam-deck.patch # temporary patches -ApplyOptionalPatch simpledrm-nvidia.patch +ApplyOptionalPatch 0001-drm-amd-pm-correct-the-metrics-version-for-SMU-11.0..patch %endif ApplyOptionalPatch linux-kernel-test.patch @@ -3044,11 +3042,18 @@ fi # # %changelog -* Mon May 23 2022 Jan Drögehoff - 5.17.9-302.fsync -- Add patch +* Sun May 29 2022 Jan Drögehoff - 5.17.11-301.fsync +- Linux v5.17.11 futex2 zen openrgb -* Sat May 21 2022 Jan Drögehoff - 5.17.9-301.fsync -- Linux v5.17.9 futex2 zen openrgb +* Wed May 25 2022 Justin M. Forbes [5.17.11-0] +- Linux v5.17.11 (Justin M. Forbes) + +* Wed May 25 2022 Justin M. Forbes [5.17.11-0] +- Linux v5.17.11 + +* Wed May 25 2022 Justin M. Forbes [5.17.10-0] +- fedora: Re-enable efifb and vesafb drivers (Javier Martinez Canillas) +- drivers/firmware: skip simpledrm if nvidia-drm.modeset=1 is set (Javier Martinez Canillas) * Wed May 18 2022 Justin M. Forbes [5.17.9-0] - Fix changelog for 5.17.8 (Justin M. Forbes) -- cgit v1.2.3