--- /dev/null
+From f056f16b2671b96992d9818eb091f95c6a9a7609 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 15:44:59 +0100
+Subject: ACPI: video: Prefer native over vendor
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit fb1836c91317e0770950260dfa91eb9b2170cb27 ]
+
+When available prefer native backlight control over vendor backlight
+control.
+
+Testing has shown that there are quite a few laptop models which rely
+on native backlight control (they don't have ACPI video bus backlight
+control) and on which acpi_osi_is_win8() returns false.
+
+Currently __acpi_video_get_backlight_type() returns vendor on these
+laptops, leading to an empty /sys/class/backlight.
+
+As a workaround for this acpi_video_backlight_use_native() has been
+temporarily changed to always return true.
+
+This re-introduces the problem of having multiple backlight
+devices under /sys/class/backlight for a single panel.
+
+Change __acpi_video_get_backlight_type() to prefer native over vendor
+when available. So that it returns native on these models.
+
+And change acpi_video_backlight_use_native() back to only return
+true when __acpi_video_get_backlight_type() returns native.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/video_detect.c | 18 +++---------------
+ 1 file changed, 3 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
+index 0c17ee93f861..76b7e7f8894e 100644
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -795,10 +795,10 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
+ return acpi_backlight_video;
+
+ /* Use native if available */
+- if (native_available && prefer_native_over_acpi_video())
++ if (native_available)
+ return acpi_backlight_native;
+
+- /* No ACPI video (old hw), use vendor specific fw methods. */
++ /* No ACPI video/native (old hw), use vendor specific fw methods. */
+ return acpi_backlight_vendor;
+ }
+
+@@ -810,18 +810,6 @@ EXPORT_SYMBOL(acpi_video_get_backlight_type);
+
+ bool acpi_video_backlight_use_native(void)
+ {
+- /*
+- * Call __acpi_video_get_backlight_type() to let it know that
+- * a native backlight is available.
+- */
+- __acpi_video_get_backlight_type(true);
+-
+- /*
+- * For now just always return true. There is a whole bunch of laptop
+- * models where (video_caps & ACPI_VIDEO_BACKLIGHT) is false causing
+- * __acpi_video_get_backlight_type() to return vendor, while these
+- * models only have a native backlight control.
+- */
+- return true;
++ return __acpi_video_get_backlight_type(true) == acpi_backlight_native;
+ }
+ EXPORT_SYMBOL(acpi_video_backlight_use_native);
+--
+2.35.1
+
--- /dev/null
+From 07ee1aab2fbf52953b8030db9818e73b113537b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 15:44:58 +0100
+Subject: ACPI: video: Simplify __acpi_video_get_backlight_type()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit a5df42521f328b45c9d89c13740e747be08ac66e ]
+
+Simplify __acpi_video_get_backlight_type() removing a nested if which
+makes the flow harder to follow.
+
+This also results in having only 1 exit point with
+return acpi_backlight_native instead of 2.
+
+Note this drops the (video_caps & ACPI_VIDEO_BACKLIGHT) check from
+the if (acpi_osi_is_win8() && native_available) return native path.
+Windows 8's hardware certification requirements include that there must
+be ACPI video bus backlight control, so the ACPI_VIDEO_BACKLIGHT check
+is redundant.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/video_detect.c | 36 +++++++++++++++++-------------------
+ 1 file changed, 17 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
+index 13f10fbcd7f0..0c17ee93f861 100644
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -734,6 +734,16 @@ static bool google_cros_ec_present(void)
+ return acpi_dev_found("GOOG0004") || acpi_dev_found("GOOG000C");
+ }
+
++/*
++ * Windows 8 and newer no longer use the ACPI video interface, so it often
++ * does not work. So on win8+ systems prefer native brightness control.
++ * Chromebooks should always prefer native backlight control.
++ */
++static bool prefer_native_over_acpi_video(void)
++{
++ return acpi_osi_is_win8() || google_cros_ec_present();
++}
++
+ /*
+ * Determine which type of backlight interface to use on this system,
+ * First check cmdline, then dmi quirks, then do autodetect.
+@@ -779,26 +789,14 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
+ if (apple_gmux_backlight_present())
+ return acpi_backlight_apple_gmux;
+
+- /* Chromebooks should always prefer native backlight control. */
+- if (google_cros_ec_present() && native_available)
+- return acpi_backlight_native;
++ /* Use ACPI video if available, except when native should be preferred. */
++ if ((video_caps & ACPI_VIDEO_BACKLIGHT) &&
++ !(native_available && prefer_native_over_acpi_video()))
++ return acpi_backlight_video;
+
+- /* On systems with ACPI video use either native or ACPI video. */
+- if (video_caps & ACPI_VIDEO_BACKLIGHT) {
+- /*
+- * Windows 8 and newer no longer use the ACPI video interface,
+- * so it often does not work. If the ACPI tables are written
+- * for win8 and native brightness ctl is available, use that.
+- *
+- * The native check deliberately is inside the if acpi-video
+- * block on older devices without acpi-video support native
+- * is usually not the best choice.
+- */
+- if (acpi_osi_is_win8() && native_available)
+- return acpi_backlight_native;
+- else
+- return acpi_backlight_video;
+- }
++ /* Use native if available */
++ if (native_available && prefer_native_over_acpi_video())
++ return acpi_backlight_native;
+
+ /* No ACPI video (old hw), use vendor specific fw methods. */
+ return acpi_backlight_vendor;
+--
+2.35.1
+
--- /dev/null
+From 1cd95b7ec464e5f764fe3104ae9ff545a3638300 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Dec 2022 14:57:13 +0000
+Subject: ALSA: hda/cirrus: Add extra 10 ms delay to allow PLL settle and lock.
+
+From: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
+
+[ Upstream commit 9fb9fa18fb50d1a33a1bd947681fce96fc2c8db6 ]
+
+New HW platforms with multiple CS42L42 parts, faster CPU and i2c
+requre some extra delay to allow PLL to settle and lock. Adding
+extra 10ms delay.
+
+Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20221205145713.23852-1-vitalyr@opensource.cirrus.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_cs8409.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
+index 754aa8ddd2e4..0ba1fbcbb21e 100644
+--- a/sound/pci/hda/patch_cs8409.c
++++ b/sound/pci/hda/patch_cs8409.c
+@@ -888,7 +888,7 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
+
+ /* Initialize CS42L42 companion codec */
+ cs8409_i2c_bulk_write(cs42l42, cs42l42->init_seq, cs42l42->init_seq_num);
+- usleep_range(20000, 25000);
++ usleep_range(30000, 35000);
+
+ /* Clear interrupts, by reading interrupt status registers */
+ cs8409_i2c_bulk_read(cs42l42, irq_regs, ARRAY_SIZE(irq_regs));
+--
+2.35.1
+
--- /dev/null
+From e2afd1275511f8ffbf35ef8c849f297bc9897d4c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Dec 2022 19:43:03 +0800
+Subject: ALSA: hda/realtek: Apply dual codec fixup for Dell Latitude laptops
+
+From: Chris Chiu <chris.chiu@canonical.com>
+
+[ Upstream commit a4517c4f3423c7c448f2c359218f97c1173523a1 ]
+
+The Dell Latiture 3340/3440/3540 laptops with Realtek ALC3204 have
+dual codecs and need the ALC1220_FIXUP_GB_DUAL_CODECS to fix the
+conflicts of Master controls. The existing headset mic fixup for
+Dell is also required to enable the jack sense and the headset mic.
+
+Introduce a new fixup to fix the dual codec and headset mic issues
+for particular Dell laptops since other old Dell laptops with the
+same codec configuration are already well handled by the fixup in
+alc269_fallback_pin_fixup_tbl[].
+
+Signed-off-by: Chris Chiu <chris.chiu@canonical.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20221226114303.4027500-1-chris.chiu@canonical.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index e443d88f627f..3794b522c222 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7175,6 +7175,7 @@ enum {
+ ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
+ ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
+ ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
++ ALC236_FIXUP_DELL_DUAL_CODECS,
+ };
+
+ /* A special fixup for Lenovo C940 and Yoga Duet 7;
+@@ -9130,6 +9131,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .chained = true,
+ .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
+ },
++ [ALC236_FIXUP_DELL_DUAL_CODECS] = {
++ .type = HDA_FIXUP_PINS,
++ .v.func = alc1220_fixup_gb_dual_codecs,
++ .chained = true,
++ .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -9232,6 +9239,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK),
+ SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
+ SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
++ SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
++ SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
++ SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
++ SND_PCI_QUIRK(0x1028, 0x0c1c, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
++ SND_PCI_QUIRK(0x1028, 0x0c1d, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
++ SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
+ SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
+--
+2.35.1
+
--- /dev/null
+From 6df1ccb2eb3ade4ae55a2ec6c1d7730c29319f19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Dec 2022 17:37:13 +0100
+Subject: ALSA: patch_realtek: Fix Dell Inspiron Plus 16
+
+From: Philipp Jungkamp <p.jungkamp@gmx.net>
+
+[ Upstream commit 2912cdda734d9136615ed05636d9fcbca2a7a3c5 ]
+
+The Dell Inspiron Plus 16, in both laptop and 2in1 form factor, has top
+speakers connected on NID 0x17, which the codec reports as unconnected.
+These speakers should be connected to the DAC on NID 0x03.
+
+Signed-off-by: Philipp Jungkamp <p.jungkamp@gmx.net>
+Link: https://lore.kernel.org/r/20221205163713.7476-1-p.jungkamp@gmx.net
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: a4517c4f3423 ("ALSA: hda/realtek: Apply dual codec fixup for Dell Latitude laptops")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 37 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index f5f640851fdc..e443d88f627f 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -6903,6 +6903,34 @@ static void alc287_fixup_yoga9_14iap7_bass_spk_pin(struct hda_codec *codec,
+ }
+ }
+
++static void alc295_fixup_dell_inspiron_top_speakers(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ static const struct hda_pintbl pincfgs[] = {
++ { 0x14, 0x90170151 },
++ { 0x17, 0x90170150 },
++ { }
++ };
++ static const hda_nid_t conn[] = { 0x02, 0x03 };
++ static const hda_nid_t preferred_pairs[] = {
++ 0x14, 0x02,
++ 0x17, 0x03,
++ 0x21, 0x02,
++ 0
++ };
++ struct alc_spec *spec = codec->spec;
++
++ alc_fixup_no_shutup(codec, fix, action);
++
++ switch (action) {
++ case HDA_FIXUP_ACT_PRE_PROBE:
++ snd_hda_apply_pincfgs(codec, pincfgs);
++ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
++ spec->gen.preferred_dacs = preferred_pairs;
++ break;
++ }
++}
++
+ enum {
+ ALC269_FIXUP_GPIO2,
+ ALC269_FIXUP_SONY_VAIO,
+@@ -7146,6 +7174,7 @@ enum {
+ ALC287_FIXUP_LEGION_16ITHG6,
+ ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
+ ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
++ ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
+ };
+
+ /* A special fixup for Lenovo C940 and Yoga Duet 7;
+@@ -9095,6 +9124,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .chained = true,
+ .chain_id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
+ },
++ [ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc295_fixup_dell_inspiron_top_speakers,
++ .chained = true,
++ .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -9195,6 +9230,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK),
+ SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK),
++ SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
++ SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
+ SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
+--
+2.35.1
+
--- /dev/null
+From 65b30f72288df82dbe93678c59d5dd0a22aaa676 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Dec 2022 16:30:37 +0100
+Subject: ALSA: usb-audio: Add new quirk FIXED_RATE for JBL Quantum810 Wireless
+
+From: Jaroslav Kysela <perex@perex.cz>
+
+[ Upstream commit fd28941cff1cd9d8ffa59fe11eb64148e09b6ed6 ]
+
+It seems that the firmware is broken and does not accept
+the UAC_EP_CS_ATTR_SAMPLE_RATE URB. There is only one rate (48000Hz)
+available in the descriptors for the output endpoint.
+
+Create a new quirk QUIRK_FLAG_FIXED_RATE to skip the rate setup
+when only one rate is available (fixed).
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216798
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Link: https://lore.kernel.org/r/20221215153037.1163786-1-perex@perex.cz
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/card.h | 1 +
+ sound/usb/endpoint.c | 16 ++++++++++------
+ sound/usb/endpoint.h | 3 ++-
+ sound/usb/implicit.c | 6 +++++-
+ sound/usb/implicit.h | 2 +-
+ sound/usb/pcm.c | 36 +++++++++++++++++++++++++++++++++---
+ sound/usb/pcm.h | 2 ++
+ sound/usb/quirks.c | 2 ++
+ sound/usb/usbaudio.h | 4 ++++
+ 9 files changed, 60 insertions(+), 12 deletions(-)
+
+diff --git a/sound/usb/card.h b/sound/usb/card.h
+index 40061550105a..6ec95b2edf86 100644
+--- a/sound/usb/card.h
++++ b/sound/usb/card.h
+@@ -131,6 +131,7 @@ struct snd_usb_endpoint {
+ bool lowlatency_playback; /* low-latency playback mode */
+ bool need_setup; /* (re-)need for hw_params? */
+ bool need_prepare; /* (re-)need for prepare? */
++ bool fixed_rate; /* skip rate setup */
+
+ /* for hw constraints */
+ const struct audioformat *cur_audiofmt;
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 4aaf0784940b..419302e2057e 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -769,7 +769,8 @@ struct snd_usb_endpoint *
+ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+ const struct audioformat *fp,
+ const struct snd_pcm_hw_params *params,
+- bool is_sync_ep)
++ bool is_sync_ep,
++ bool fixed_rate)
+ {
+ struct snd_usb_endpoint *ep;
+ int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint;
+@@ -825,6 +826,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+ ep->implicit_fb_sync = fp->implicit_fb;
+ ep->need_setup = true;
+ ep->need_prepare = true;
++ ep->fixed_rate = fixed_rate;
+
+ usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n",
+ ep->cur_channels, ep->cur_rate,
+@@ -1413,11 +1415,13 @@ static int init_sample_rate(struct snd_usb_audio *chip,
+ if (clock && !clock->need_setup)
+ return 0;
+
+- err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
+- if (err < 0) {
+- if (clock)
+- clock->rate = 0; /* reset rate */
+- return err;
++ if (!ep->fixed_rate) {
++ err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
++ if (err < 0) {
++ if (clock)
++ clock->rate = 0; /* reset rate */
++ return err;
++ }
+ }
+
+ if (clock)
+diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
+index e67ea28faa54..924f4351588c 100644
+--- a/sound/usb/endpoint.h
++++ b/sound/usb/endpoint.h
+@@ -14,7 +14,8 @@ struct snd_usb_endpoint *
+ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+ const struct audioformat *fp,
+ const struct snd_pcm_hw_params *params,
+- bool is_sync_ep);
++ bool is_sync_ep,
++ bool fixed_rate);
+ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+ struct snd_usb_endpoint *ep);
+ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
+index f3e8484b3d9c..41ac7185b42b 100644
+--- a/sound/usb/implicit.c
++++ b/sound/usb/implicit.c
+@@ -15,6 +15,7 @@
+ #include "usbaudio.h"
+ #include "card.h"
+ #include "helper.h"
++#include "pcm.h"
+ #include "implicit.h"
+
+ enum {
+@@ -455,7 +456,8 @@ const struct audioformat *
+ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+ const struct audioformat *target,
+ const struct snd_pcm_hw_params *params,
+- int stream)
++ int stream,
++ bool *fixed_rate)
+ {
+ struct snd_usb_substream *subs;
+ const struct audioformat *fp, *sync_fmt = NULL;
+@@ -483,6 +485,8 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+ }
+ }
+
++ if (fixed_rate)
++ *fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
+ return sync_fmt;
+ }
+
+diff --git a/sound/usb/implicit.h b/sound/usb/implicit.h
+index ccb415a0ea86..7f1577b6c4d3 100644
+--- a/sound/usb/implicit.h
++++ b/sound/usb/implicit.h
+@@ -9,6 +9,6 @@ const struct audioformat *
+ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+ const struct audioformat *target,
+ const struct snd_pcm_hw_params *params,
+- int stream);
++ int stream, bool *fixed_rate);
+
+ #endif /* __USBAUDIO_IMPLICIT_H */
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index 9557bd4d1bbc..99a66d0ef5b2 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -157,6 +157,31 @@ find_substream_format(struct snd_usb_substream *subs,
+ true, subs);
+ }
+
++bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
++{
++ const struct audioformat *fp;
++ struct snd_usb_audio *chip = subs->stream->chip;
++ int rate = -1;
++
++ if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
++ return false;
++ list_for_each_entry(fp, &subs->fmt_list, list) {
++ if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
++ return false;
++ if (fp->nr_rates < 1)
++ continue;
++ if (fp->nr_rates > 1)
++ return false;
++ if (rate < 0) {
++ rate = fp->rate_table[0];
++ continue;
++ }
++ if (rate != fp->rate_table[0])
++ return false;
++ }
++ return true;
++}
++
+ static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
+ {
+ struct usb_device *dev = chip->dev;
+@@ -450,12 +475,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ struct snd_usb_audio *chip = subs->stream->chip;
+ const struct audioformat *fmt;
+ const struct audioformat *sync_fmt;
++ bool fixed_rate, sync_fixed_rate;
+ int ret;
+
+ ret = snd_media_start_pipeline(subs);
+ if (ret)
+ return ret;
+
++ fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
+ fmt = find_substream_format(subs, hw_params);
+ if (!fmt) {
+ usb_audio_dbg(chip,
+@@ -469,7 +496,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ if (fmt->implicit_fb) {
+ sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
+ hw_params,
+- !substream->stream);
++ !substream->stream,
++ &sync_fixed_rate);
+ if (!sync_fmt) {
+ usb_audio_dbg(chip,
+ "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n",
+@@ -482,6 +510,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ }
+ } else {
+ sync_fmt = fmt;
++ sync_fixed_rate = fixed_rate;
+ }
+
+ ret = snd_usb_lock_shutdown(chip);
+@@ -499,7 +528,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ close_endpoints(chip, subs);
+ }
+
+- subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false);
++ subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false, fixed_rate);
+ if (!subs->data_endpoint) {
+ ret = -EINVAL;
+ goto unlock;
+@@ -508,7 +537,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ if (fmt->sync_ep) {
+ subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,
+ hw_params,
+- fmt == sync_fmt);
++ fmt == sync_fmt,
++ sync_fixed_rate);
+ if (!subs->sync_endpoint) {
+ ret = -EINVAL;
+ goto unlock;
+diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
+index 493a4e34d78d..388fe2ba346d 100644
+--- a/sound/usb/pcm.h
++++ b/sound/usb/pcm.h
+@@ -6,6 +6,8 @@ void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
+ int snd_usb_pcm_suspend(struct snd_usb_stream *as);
+ int snd_usb_pcm_resume(struct snd_usb_stream *as);
+
++bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *as);
++
+ int snd_usb_init_pitch(struct snd_usb_audio *chip,
+ const struct audioformat *fmt);
+ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 58b37bfc885c..3d13fdf7590c 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2152,6 +2152,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
+ QUIRK_FLAG_IFACE_SKIP_CLOSE),
++ DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
++ QUIRK_FLAG_FIXED_RATE),
+
+ /* Vendor matches */
+ VENDOR_FLG(0x045e, /* MS Lifecam */
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index 2aba508a4831..f5a8dca66457 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -175,6 +175,9 @@ extern bool snd_usb_skip_validation;
+ * QUIRK_FLAG_FORCE_IFACE_RESET
+ * Force an interface reset whenever stopping & restarting a stream
+ * (e.g. after xrun)
++ * QUIRK_FLAG_FIXED_RATE
++ * Do not set PCM rate (frequency) when only one rate is available
++ * for the given endpoint.
+ */
+
+ #define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0)
+@@ -198,5 +201,6 @@ extern bool snd_usb_skip_validation;
+ #define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18)
+ #define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19)
+ #define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20)
++#define QUIRK_FLAG_FIXED_RATE (1U << 21)
+
+ #endif /* __USBAUDIO_H */
+--
+2.35.1
+
--- /dev/null
+From 824e9a447e4481a490f532dbe884a4f5b77edc8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Dec 2022 00:02:53 +0100
+Subject: bpf: Resolve fext program type when checking map compatibility
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke HĂžiland-JĂžrgensen <toke@redhat.com>
+
+[ Upstream commit 1c123c567fb138ebd187480b7fc0610fcb0851f5 ]
+
+The bpf_prog_map_compatible() check makes sure that BPF program types are
+not mixed inside BPF map types that can contain programs (tail call maps,
+cpumaps and devmaps). It does this by setting the fields of the map->owner
+struct to the values of the first program being checked against, and
+rejecting any subsequent programs if the values don't match.
+
+One of the values being set in the map owner struct is the program type,
+and since the code did not resolve the prog type for fext programs, the map
+owner type would be set to PROG_TYPE_EXT and subsequent loading of programs
+of the target type into the map would fail.
+
+This bug is seen in particular for XDP programs that are loaded as
+PROG_TYPE_EXT using libxdp; these cannot insert programs into devmaps and
+cpumaps because the check fails as described above.
+
+Fix the bug by resolving the fext program type to its target program type
+as elsewhere in the verifier.
+
+v3:
+- Add Yonghong's ACK
+
+Fixes: f45d5b6ce2e8 ("bpf: generalise tail call map compatibility check")
+Acked-by: Yonghong Song <yhs@fb.com>
+Signed-off-by: Toke HĂžiland-JĂžrgensen <toke@redhat.com>
+Link: https://lore.kernel.org/r/20221214230254.790066-1-toke@redhat.com
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bpf_verifier.h | 2 +-
+ kernel/bpf/core.c | 5 +++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
+index 9e1e6965f407..0eb8f035b3d9 100644
+--- a/include/linux/bpf_verifier.h
++++ b/include/linux/bpf_verifier.h
+@@ -642,7 +642,7 @@ static inline u32 type_flag(u32 type)
+ }
+
+ /* only use after check_attach_btf_id() */
+-static inline enum bpf_prog_type resolve_prog_type(struct bpf_prog *prog)
++static inline enum bpf_prog_type resolve_prog_type(const struct bpf_prog *prog)
+ {
+ return prog->type == BPF_PROG_TYPE_EXT ?
+ prog->aux->dst_prog->type : prog->type;
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 25a54e04560e..17ab3e15ac25 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -2088,6 +2088,7 @@ static unsigned int __bpf_prog_ret0_warn(const void *ctx,
+ bool bpf_prog_map_compatible(struct bpf_map *map,
+ const struct bpf_prog *fp)
+ {
++ enum bpf_prog_type prog_type = resolve_prog_type(fp);
+ bool ret;
+
+ if (fp->kprobe_override)
+@@ -2098,12 +2099,12 @@ bool bpf_prog_map_compatible(struct bpf_map *map,
+ /* There's no owner yet where we could check for
+ * compatibility.
+ */
+- map->owner.type = fp->type;
++ map->owner.type = prog_type;
+ map->owner.jited = fp->jited;
+ map->owner.xdp_has_frags = fp->aux->xdp_has_frags;
+ ret = true;
+ } else {
+- ret = map->owner.type == fp->type &&
++ ret = map->owner.type == prog_type &&
+ map->owner.jited == fp->jited &&
+ map->owner.xdp_has_frags == fp->aux->xdp_has_frags;
+ }
+--
+2.35.1
+
--- /dev/null
+From 38a2d620102fe1a2fd5be9502ab8d6fcc1707486 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Nov 2022 18:49:32 +0100
+Subject: HID: Ignore HP Envy x360 eu0009nv stylus battery
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: José Expósito <jose.exposito89@gmail.com>
+
+[ Upstream commit cec827d658dd5c287ea8925737d45f0a60e47422 ]
+
+Battery status is reported for the HP Envy x360 eu0009nv stylus even
+though it does not have battery.
+
+Prevent it from always reporting the battery as low (1%).
+
+Link: https://gitlab.freedesktop.org/libinput/libinput/-/issues/823
+Reported-by: Ioannis Iliopoulos <jxftw2424@gmail.com>
+Tested-by: Ioannis Iliopoulos <jxftw2424@gmail.com>
+Signed-off-by: José Expósito <jose.exposito89@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 e27fb27a36bf..82713ef3aaa6 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -412,6 +412,7 @@
+ #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
+ #define I2C_DEVICE_ID_HP_ENVY_X360_15 0x2d05
+ #define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100 0x29CF
++#define I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV 0x2CF9
+ #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817
+ #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544
+ #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index d728a94c642e..3ee5a9fea20e 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -380,6 +380,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
+ HID_BATTERY_QUIRK_IGNORE },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100),
+ HID_BATTERY_QUIRK_IGNORE },
++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV),
++ HID_BATTERY_QUIRK_IGNORE },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15),
+ HID_BATTERY_QUIRK_IGNORE },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN),
+--
+2.35.1
+
--- /dev/null
+From 1f23f01c9edd864b372c9a9d23548369db632969 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 29 Oct 2022 15:03:09 +0300
+Subject: platform/x86: ideapad-laptop: Add new _CFG bit numbers for future use
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eray Orçunus <erayorcunus@gmail.com>
+
+[ Upstream commit be5dd7d8359de9fb22115a63f09981cdf689db4f ]
+
+Later IdeaPads report various things in last 8 bits of _CFG, at least
+5 of them represent supported on-screen-displays. Add those bit numbers
+to the enum, and use CFG_OSD_ as prefix of their names. Also expose
+the values of these bits to debugfs, since they can be useful.
+
+Signed-off-by: Eray Orçunus <erayorcunus@gmail.com>
+Acked-by: Ike Panhc <ike.pan@canonical.com>
+Link: https://lore.kernel.org/r/20221029120311.11152-5-erayorcunus@gmail.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 33 +++++++++++++++++++++++----
+ 1 file changed, 29 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 7192e0d2a14f..125b4534424f 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -46,10 +46,22 @@ static const char *const ideapad_wmi_fnesc_events[] = {
+ #endif
+
+ enum {
+- CFG_CAP_BT_BIT = 16,
+- CFG_CAP_3G_BIT = 17,
+- CFG_CAP_WIFI_BIT = 18,
+- CFG_CAP_CAM_BIT = 19,
++ CFG_CAP_BT_BIT = 16,
++ CFG_CAP_3G_BIT = 17,
++ CFG_CAP_WIFI_BIT = 18,
++ CFG_CAP_CAM_BIT = 19,
++
++ /*
++ * These are OnScreenDisplay support bits that can be useful to determine
++ * whether a hotkey exists/should show OSD. But they aren't particularly
++ * meaningful since they were introduced later, i.e. 2010 IdeaPads
++ * don't have these, but they still have had OSD for hotkeys.
++ */
++ CFG_OSD_NUMLK_BIT = 27,
++ CFG_OSD_CAPSLK_BIT = 28,
++ CFG_OSD_MICMUTE_BIT = 29,
++ CFG_OSD_TOUCHPAD_BIT = 30,
++ CFG_OSD_CAM_BIT = 31,
+ };
+
+ enum {
+@@ -387,6 +399,19 @@ static int debugfs_cfg_show(struct seq_file *s, void *data)
+ seq_puts(s, " camera");
+ seq_puts(s, "\n");
+
++ seq_puts(s, "OSD support:");
++ if (test_bit(CFG_OSD_NUMLK_BIT, &priv->cfg))
++ seq_puts(s, " num-lock");
++ if (test_bit(CFG_OSD_CAPSLK_BIT, &priv->cfg))
++ seq_puts(s, " caps-lock");
++ if (test_bit(CFG_OSD_MICMUTE_BIT, &priv->cfg))
++ seq_puts(s, " mic-mute");
++ if (test_bit(CFG_OSD_TOUCHPAD_BIT, &priv->cfg))
++ seq_puts(s, " touchpad");
++ if (test_bit(CFG_OSD_CAM_BIT, &priv->cfg))
++ seq_puts(s, " camera");
++ seq_puts(s, "\n");
++
+ seq_puts(s, "Graphics: ");
+ switch (priv->cfg & 0x700) {
+ case 0x100:
+--
+2.35.1
+
--- /dev/null
+From 3b390ad25f7a126ce6a0fe4d6b0b0c565d7e0793 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 12:02:40 +0100
+Subject: platform/x86: ideapad-laptop: Do not send KEY_TOUCHPAD* events on
+ probe / resume
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit f4dd8c44bb831ff885680bc77111fa39c193a93f ]
+
+The sending of KEY_TOUCHPAD* events is causing spurious touchpad OSD
+showing on resume.
+
+Disable the sending of events on probe / resume to fix this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+Link: https://lore.kernel.org/r/20221117110244.67811-3-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index dcb3a82024da..eb0b1ec32c13 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -1487,7 +1487,7 @@ static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
+ /*
+ * module init/exit
+ */
+-static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
++static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_events)
+ {
+ unsigned long value;
+ unsigned char param;
+@@ -1508,8 +1508,11 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
+ * KEY_TOUCHPAD_ON to not to get out of sync with LED
+ */
+ i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
+- ideapad_input_report(priv, value ? 67 : 66);
+- sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
++
++ if (send_events) {
++ ideapad_input_report(priv, value ? 67 : 66);
++ sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
++ }
+ }
+
+ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
+@@ -1550,7 +1553,7 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
+ ideapad_sync_rfk_state(priv);
+ break;
+ case 5:
+- ideapad_sync_touchpad_state(priv);
++ ideapad_sync_touchpad_state(priv, true);
+ break;
+ case 4:
+ ideapad_backlight_notify_brightness(priv);
+@@ -1840,7 +1843,7 @@ static int ideapad_acpi_add(struct platform_device *pdev)
+ ideapad_register_rfkill(priv, i);
+
+ ideapad_sync_rfk_state(priv);
+- ideapad_sync_touchpad_state(priv);
++ ideapad_sync_touchpad_state(priv, false);
+
+ err = ideapad_dytc_profile_init(priv);
+ if (err) {
+@@ -1925,7 +1928,7 @@ static int ideapad_acpi_resume(struct device *dev)
+ struct ideapad_private *priv = dev_get_drvdata(dev);
+
+ ideapad_sync_rfk_state(priv);
+- ideapad_sync_touchpad_state(priv);
++ ideapad_sync_touchpad_state(priv, false);
+
+ if (priv->dytc)
+ dytc_profile_refresh(priv);
+--
+2.35.1
+
--- /dev/null
+From 08ae3377b2125e20f30cfe3c7cbb8a0d5dcead90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 12:02:41 +0100
+Subject: platform/x86: ideapad-laptop: Only toggle ps2 aux port on/off on
+ select models
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit c69e7d843d2c34b80b8731a5dc57c34ea04a3edf ]
+
+Recently there have been multiple patches to disable the ideapad-laptop's
+touchpad control code, because it is causing issues on various laptops:
+
+Commit d69cd7eea93e ("platform/x86: ideapad-laptop: Disable touchpad_switch for ELAN0634")
+Commit a231224a601c ("platform/x86: ideapad-laptop: Disable touchpad_switch")
+
+The turning on/off of the ps2 aux port was added specifically for
+the IdeaPad Z570, where the EC does toggle the touchpad on/off LED and
+toggles the value returned by reading VPCCMD_R_TOUCHPAD, but it does not
+actually turn on/off the touchpad.
+
+The ideapad-laptop code really should not be messing with the i8042
+controller on all devices just for this special case.
+
+Add a new ctrl_ps2_aux_port flag set based on a DMI based allow-list
+for devices which need this workaround, populating it with just
+the Ideapad Z570 for now.
+
+This also adds a module parameter so that this behavior can easily
+be enabled on other models which may need it.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+Link: https://lore.kernel.org/r/20221117110244.67811-4-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 29 ++++++++++++++++++++++++++-
+ 1 file changed, 28 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index eb0b1ec32c13..1d86fb988d56 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -143,6 +143,7 @@ struct ideapad_private {
+ bool hw_rfkill_switch : 1;
+ bool kbd_bl : 1;
+ bool touchpad_ctrl_via_ec : 1;
++ bool ctrl_ps2_aux_port : 1;
+ bool usb_charging : 1;
+ } features;
+ struct {
+@@ -174,6 +175,12 @@ MODULE_PARM_DESC(set_fn_lock_led,
+ "Enable driver based updates of the fn-lock LED on fn-lock changes. "
+ "If you need this please report this to: platform-driver-x86@vger.kernel.org");
+
++static bool ctrl_ps2_aux_port;
++module_param(ctrl_ps2_aux_port, bool, 0444);
++MODULE_PARM_DESC(ctrl_ps2_aux_port,
++ "Enable driver based PS/2 aux port en-/dis-abling on touchpad on/off toggle. "
++ "If you need this please report this to: platform-driver-x86@vger.kernel.org");
++
+ /*
+ * shared data
+ */
+@@ -1507,7 +1514,8 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
+ * touchpad off and on. We send KEY_TOUCHPAD_OFF and
+ * KEY_TOUCHPAD_ON to not to get out of sync with LED
+ */
+- i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
++ if (priv->features.ctrl_ps2_aux_port)
++ i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
+
+ if (send_events) {
+ ideapad_input_report(priv, value ? 67 : 66);
+@@ -1615,6 +1623,23 @@ static const struct dmi_system_id hw_rfkill_list[] = {
+ {}
+ };
+
++/*
++ * On some models the EC toggles the touchpad muted LED on touchpad toggle
++ * hotkey presses, but the EC does not actually disable the touchpad itself.
++ * On these models the driver needs to explicitly enable/disable the i8042
++ * (PS/2) aux port.
++ */
++static const struct dmi_system_id ctrl_ps2_aux_port_list[] = {
++ {
++ /* Lenovo Ideapad Z570 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
++ },
++ },
++ {}
++};
++
+ static const struct dmi_system_id no_touchpad_switch_list[] = {
+ {
+ .ident = "Lenovo Yoga 3 Pro 1370",
+@@ -1642,6 +1667,8 @@ static void ideapad_check_features(struct ideapad_private *priv)
+ set_fn_lock_led || dmi_check_system(set_fn_lock_led_list);
+ priv->features.hw_rfkill_switch =
+ hw_rfkill_switch || dmi_check_system(hw_rfkill_list);
++ priv->features.ctrl_ps2_aux_port =
++ ctrl_ps2_aux_port || dmi_check_system(ctrl_ps2_aux_port_list);
+
+ /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
+ if (acpi_dev_present("ELAN0634", NULL, -1))
+--
+2.35.1
+
--- /dev/null
+From 0bb1a9c91a0c552f91be0ca5b9a9bda6b44961e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 12:02:39 +0100
+Subject: platform/x86: ideapad-laptop: Refactor ideapad_sync_touchpad_state()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 289a59895e7a380cdc7fe2780d3073f4b9237020 ]
+
+Add an error exit for read_ec_data() failing instead of putting the main
+body in an if (success) block.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+Link: https://lore.kernel.org/r/20221117110244.67811-2-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 27 +++++++++++++++------------
+ 1 file changed, 15 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 13e3ae731fd8..dcb3a82024da 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -1490,23 +1490,26 @@ static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
+ static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
+ {
+ unsigned long value;
++ unsigned char param;
++ int ret;
+
+ if (!priv->features.touchpad_ctrl_via_ec)
+ return;
+
+ /* Without reading from EC touchpad LED doesn't switch state */
+- if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
+- unsigned char param;
+- /*
+- * Some IdeaPads don't really turn off touchpad - they only
+- * switch the LED state. We (de)activate KBC AUX port to turn
+- * touchpad off and on. We send KEY_TOUCHPAD_OFF and
+- * KEY_TOUCHPAD_ON to not to get out of sync with LED
+- */
+- i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
+- ideapad_input_report(priv, value ? 67 : 66);
+- sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
+- }
++ ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value);
++ if (ret)
++ return;
++
++ /*
++ * Some IdeaPads don't really turn off touchpad - they only
++ * switch the LED state. We (de)activate KBC AUX port to turn
++ * touchpad off and on. We send KEY_TOUCHPAD_OFF and
++ * KEY_TOUCHPAD_ON to not to get out of sync with LED
++ */
++ i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
++ ideapad_input_report(priv, value ? 67 : 66);
++ sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
+ }
+
+ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
+--
+2.35.1
+
--- /dev/null
+From cded754f8dbf018e91e01a1cff6ebe7ed2df158a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 29 Oct 2022 15:03:06 +0300
+Subject: platform/x86: ideapad-laptop: Revert "check for touchpad support in
+ _CFG"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eray Orçunus <erayorcunus@gmail.com>
+
+[ Upstream commit 5831882880e9a1749553e78f9d8369fe33116aaf ]
+
+Last 8 bit of _CFG started being used in later IdeaPads, thus 30th bit
+doesn't always show whether device supports touchpad or touchpad switch.
+Remove checking bit 30 of _CFG, so older IdeaPads like S10-3 can switch
+touchpad again via touchpad attribute.
+
+This reverts commit b3ed1b7fe378 ("platform/x86: ideapad-laptop: check for
+touchpad support in _CFG").
+
+Signed-off-by: Eray Orçunus <erayorcunus@gmail.com>
+Acked-by: Ike Panhc <ike.pan@canonical.com>
+Link: https://lore.kernel.org/r/20221029120311.11152-2-erayorcunus@gmail.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 3ea8fc6a9ca3..7192e0d2a14f 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -46,11 +46,10 @@ static const char *const ideapad_wmi_fnesc_events[] = {
+ #endif
+
+ enum {
+- CFG_CAP_BT_BIT = 16,
+- CFG_CAP_3G_BIT = 17,
+- CFG_CAP_WIFI_BIT = 18,
+- CFG_CAP_CAM_BIT = 19,
+- CFG_CAP_TOUCHPAD_BIT = 30,
++ CFG_CAP_BT_BIT = 16,
++ CFG_CAP_3G_BIT = 17,
++ CFG_CAP_WIFI_BIT = 18,
++ CFG_CAP_CAM_BIT = 19,
+ };
+
+ enum {
+@@ -386,8 +385,6 @@ static int debugfs_cfg_show(struct seq_file *s, void *data)
+ seq_puts(s, " wifi");
+ if (test_bit(CFG_CAP_CAM_BIT, &priv->cfg))
+ seq_puts(s, " camera");
+- if (test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg))
+- seq_puts(s, " touchpad");
+ seq_puts(s, "\n");
+
+ seq_puts(s, "Graphics: ");
+@@ -680,8 +677,7 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
+ else if (attr == &dev_attr_fn_lock.attr)
+ supported = priv->features.fn_lock;
+ else if (attr == &dev_attr_touchpad.attr)
+- supported = priv->features.touchpad_ctrl_via_ec &&
+- test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg);
++ supported = priv->features.touchpad_ctrl_via_ec;
+ else if (attr == &dev_attr_usb_charging.attr)
+ supported = priv->features.usb_charging;
+
+--
+2.35.1
+
--- /dev/null
+From a6133ba67494d34ba7843e9db42fe9e5271bbe58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 12:02:42 +0100
+Subject: platform/x86: ideapad-laptop: Send KEY_TOUCHPAD_TOGGLE on some models
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 5829f8a897e4f030cd2d32a930eea8954ab5dcd3 ]
+
+On recent Ideapad models the EC does not control the touchpad at all,
+so instead of sending KEY_TOUCHPAD_ON/ _OFF on touchpad toggle hotkey
+events, ideapad-laptop should send KEY_TOUCHPAD_TOGGLE and let userspace
+handle the toggling.
+
+Check for this by checking if the value read from VPCCMD_R_TOUCHPAD
+actually changes when receiving a touchpad-toggle hotkey event; and
+if it does not change send KEY_TOUCHPAD_TOGGLE to userspace to let
+userspace enable/disable the touchpad in software.
+
+Note this also drops the priv->features.touchpad_ctrl_via_ec check from
+ideapad_sync_touchpad_state() so that KEY_TOUCHPAD_TOGGLE will be send
+on laptops where this is not set too. This can be safely dropped now
+because the i8042_command(I8042_CMD_AUX_ENABLE/_DISABLE) call is now
+guarded by its own feature flag.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+Link: https://lore.kernel.org/r/20221117110244.67811-5-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 1d86fb988d56..9b36cfddd36f 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -134,6 +134,7 @@ struct ideapad_private {
+ struct ideapad_dytc_priv *dytc;
+ struct dentry *debug;
+ unsigned long cfg;
++ unsigned long r_touchpad_val;
+ struct {
+ bool conservation_mode : 1;
+ bool dytc : 1;
+@@ -650,6 +651,8 @@ static ssize_t touchpad_show(struct device *dev,
+ if (err)
+ return err;
+
++ priv->r_touchpad_val = result;
++
+ return sysfs_emit(buf, "%d\n", !!result);
+ }
+
+@@ -669,6 +672,8 @@ static ssize_t touchpad_store(struct device *dev,
+ if (err)
+ return err;
+
++ priv->r_touchpad_val = state;
++
+ return count;
+ }
+
+@@ -1159,6 +1164,7 @@ static const struct key_entry ideapad_keymap[] = {
+ { KE_KEY, 65, { KEY_PROG4 } },
+ { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
+ { KE_KEY, 67, { KEY_TOUCHPAD_ON } },
++ { KE_KEY, 68, { KEY_TOUCHPAD_TOGGLE } },
+ { KE_KEY, 128, { KEY_ESC } },
+
+ /*
+@@ -1500,9 +1506,6 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
+ unsigned char param;
+ int ret;
+
+- if (!priv->features.touchpad_ctrl_via_ec)
+- return;
+-
+ /* Without reading from EC touchpad LED doesn't switch state */
+ ret = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value);
+ if (ret)
+@@ -1518,9 +1521,20 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
+ i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
+
+ if (send_events) {
+- ideapad_input_report(priv, value ? 67 : 66);
+- sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
++ /*
++ * On older models the EC controls the touchpad and toggles it
++ * on/off itself, in this case we report KEY_TOUCHPAD_ON/_OFF.
++ * If the EC did not toggle, report KEY_TOUCHPAD_TOGGLE.
++ */
++ if (value != priv->r_touchpad_val) {
++ ideapad_input_report(priv, value ? 67 : 66);
++ sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
++ } else {
++ ideapad_input_report(priv, 68);
++ }
+ }
++
++ priv->r_touchpad_val = value;
+ }
+
+ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
+--
+2.35.1
+
--- /dev/null
+From 4d9a7638a44e4768da2ba06180db0488c2bbdbe5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 12:02:43 +0100
+Subject: platform/x86: ideapad-laptop: Stop writing VPCCMD_W_TOUCHPAD at probe
+ time
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit a10ba160d427e78ffa2ab15a86cacaec291fa58a ]
+
+Commit d69cd7eea93e ("platform/x86: ideapad-laptop: Disable touchpad_switch
+for ELAN0634") from Janary 2021 added a flag hiding the touchpad sysfs-attr
+and disabling ideapad_sync_touchpad_state() because some devices
+"do not use EC to switch touchpad".
+
+At the same time this added a write(VPCCMD_W_TOUCHPAD, 1) call at probe
+time on these same devices. This seems to be copied from the rfkill code
+which does something similar when hw rfkill support is disabled.
+
+But for the rfkill code this is known to be necessary on some models,
+where as for the touchpad control no motivation is given for doing this
+and prior to this patch there were no reports of needing to do this.
+
+So this seems unnecessary; and it is best to avoid poking the hardware
+unnecessary to avoid unwanted side effects, so remove this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Tested-by: Maxim Mikityanskiy <maxtram95@gmail.com>
+Link: https://lore.kernel.org/r/20221117110244.67811-6-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 9b36cfddd36f..fc3d47a75944 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -1875,10 +1875,6 @@ static int ideapad_acpi_add(struct platform_device *pdev)
+ if (!priv->features.hw_rfkill_switch)
+ write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
+
+- /* The same for Touchpad */
+- if (!priv->features.touchpad_ctrl_via_ec)
+- write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
+-
+ for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
+ if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
+ ideapad_register_rfkill(priv, i);
+--
+2.35.1
+
--- /dev/null
+From 8a1574a69aebcd8279a99fe1407bb3858b930b56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Nov 2022 12:06:47 +0100
+Subject: platform/x86: ideapad-laptop: support for more special keys in WMI
+
+From: Philipp Jungkamp <p.jungkamp@gmx.net>
+
+[ Upstream commit f32e02417614d3588a3954dab2a70320c43d1010 ]
+
+The event data of the WMI event 0xD0, which is assumed to be the
+fn_lock, is used to indicate several special keys on newer Yoga 7/9
+laptops.
+
+The notify_id 0xD0 is non-unique in the DSDT of the Yoga 9 14IAP7, this
+causes wmi_get_event_data() to report wrong values.
+Port the ideapad-laptop WMI code to the wmi bus infrastructure which
+does not suffer from the shortcomings of wmi_get_event_data().
+
+Signed-off-by: Philipp Jungkamp <p.jungkamp@gmx.net>
+Link: https://lore.kernel.org/r/20221116110647.3438-1-p.jungkamp@gmx.net
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 261 ++++++++++++++++++++------
+ 1 file changed, 202 insertions(+), 59 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 125b4534424f..13e3ae731fd8 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -30,6 +30,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/sysfs.h>
+ #include <linux/types.h>
++#include <linux/wmi.h>
+
+ #include <acpi/video.h>
+
+@@ -37,14 +38,6 @@
+
+ #define IDEAPAD_RFKILL_DEV_NUM 3
+
+-#if IS_ENABLED(CONFIG_ACPI_WMI)
+-static const char *const ideapad_wmi_fnesc_events[] = {
+- "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */
+- "56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */
+- "8FC0DE0C-B4E4-43FD-B0F3-8871711C1294", /* Legion 5 */
+-};
+-#endif
+-
+ enum {
+ CFG_CAP_BT_BIT = 16,
+ CFG_CAP_3G_BIT = 17,
+@@ -141,7 +134,6 @@ struct ideapad_private {
+ struct ideapad_dytc_priv *dytc;
+ struct dentry *debug;
+ unsigned long cfg;
+- const char *fnesc_guid;
+ struct {
+ bool conservation_mode : 1;
+ bool dytc : 1;
+@@ -182,6 +174,42 @@ MODULE_PARM_DESC(set_fn_lock_led,
+ "Enable driver based updates of the fn-lock LED on fn-lock changes. "
+ "If you need this please report this to: platform-driver-x86@vger.kernel.org");
+
++/*
++ * shared data
++ */
++
++static struct ideapad_private *ideapad_shared;
++static DEFINE_MUTEX(ideapad_shared_mutex);
++
++static int ideapad_shared_init(struct ideapad_private *priv)
++{
++ int ret;
++
++ mutex_lock(&ideapad_shared_mutex);
++
++ if (!ideapad_shared) {
++ ideapad_shared = priv;
++ ret = 0;
++ } else {
++ dev_warn(&priv->adev->dev, "found multiple platform devices\n");
++ ret = -EINVAL;
++ }
++
++ mutex_unlock(&ideapad_shared_mutex);
++
++ return ret;
++}
++
++static void ideapad_shared_exit(struct ideapad_private *priv)
++{
++ mutex_lock(&ideapad_shared_mutex);
++
++ if (ideapad_shared == priv)
++ ideapad_shared = NULL;
++
++ mutex_unlock(&ideapad_shared_mutex);
++}
++
+ /*
+ * ACPI Helpers
+ */
+@@ -1110,6 +1138,8 @@ static void ideapad_sysfs_exit(struct ideapad_private *priv)
+ /*
+ * input device
+ */
++#define IDEAPAD_WMI_KEY 0x100
++
+ static const struct key_entry ideapad_keymap[] = {
+ { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, 7, { KEY_CAMERA } },
+@@ -1123,6 +1153,28 @@ static const struct key_entry ideapad_keymap[] = {
+ { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
+ { KE_KEY, 67, { KEY_TOUCHPAD_ON } },
+ { KE_KEY, 128, { KEY_ESC } },
++
++ /*
++ * WMI keys
++ */
++
++ /* FnLock (handled by the firmware) */
++ { KE_IGNORE, 0x02 | IDEAPAD_WMI_KEY },
++ /* Esc (handled by the firmware) */
++ { KE_IGNORE, 0x03 | IDEAPAD_WMI_KEY },
++ /* Customizable Lenovo Hotkey ("star" with 'S' inside) */
++ { KE_KEY, 0x01 | IDEAPAD_WMI_KEY, { KEY_FAVORITES } },
++ /* Dark mode toggle */
++ { KE_KEY, 0x13 | IDEAPAD_WMI_KEY, { KEY_PROG1 } },
++ /* Sound profile switch */
++ { KE_KEY, 0x12 | IDEAPAD_WMI_KEY, { KEY_PROG2 } },
++ /* Lenovo Virtual Background application */
++ { KE_KEY, 0x28 | IDEAPAD_WMI_KEY, { KEY_PROG3 } },
++ /* Lenovo Support */
++ { KE_KEY, 0x27 | IDEAPAD_WMI_KEY, { KEY_HELP } },
++ /* Refresh Rate Toggle */
++ { KE_KEY, 0x0a | IDEAPAD_WMI_KEY, { KEY_DISPLAYTOGGLE } },
++
+ { KE_END },
+ };
+
+@@ -1526,33 +1578,6 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
+ }
+ }
+
+-#if IS_ENABLED(CONFIG_ACPI_WMI)
+-static void ideapad_wmi_notify(u32 value, void *context)
+-{
+- struct ideapad_private *priv = context;
+- unsigned long result;
+-
+- switch (value) {
+- case 128:
+- ideapad_input_report(priv, value);
+- break;
+- case 208:
+- if (!priv->features.set_fn_lock_led)
+- break;
+-
+- if (!eval_hals(priv->adev->handle, &result)) {
+- bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
+-
+- exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
+- }
+- break;
+- default:
+- dev_info(&priv->platform_device->dev,
+- "Unknown WMI event: %u\n", value);
+- }
+-}
+-#endif
+-
+ /* On some models we need to call exec_sals(SALS_FNLOCK_ON/OFF) to set the LED */
+ static const struct dmi_system_id set_fn_lock_led_list[] = {
+ {
+@@ -1643,6 +1668,118 @@ static void ideapad_check_features(struct ideapad_private *priv)
+ }
+ }
+
++#if IS_ENABLED(CONFIG_ACPI_WMI)
++/*
++ * WMI driver
++ */
++enum ideapad_wmi_event_type {
++ IDEAPAD_WMI_EVENT_ESC,
++ IDEAPAD_WMI_EVENT_FN_KEYS,
++};
++
++struct ideapad_wmi_private {
++ enum ideapad_wmi_event_type event;
++};
++
++static int ideapad_wmi_probe(struct wmi_device *wdev, const void *context)
++{
++ struct ideapad_wmi_private *wpriv;
++
++ wpriv = devm_kzalloc(&wdev->dev, sizeof(*wpriv), GFP_KERNEL);
++ if (!wpriv)
++ return -ENOMEM;
++
++ *wpriv = *(const struct ideapad_wmi_private *)context;
++
++ dev_set_drvdata(&wdev->dev, wpriv);
++ return 0;
++}
++
++static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data)
++{
++ struct ideapad_wmi_private *wpriv = dev_get_drvdata(&wdev->dev);
++ struct ideapad_private *priv;
++ unsigned long result;
++
++ mutex_lock(&ideapad_shared_mutex);
++
++ priv = ideapad_shared;
++ if (!priv)
++ goto unlock;
++
++ switch (wpriv->event) {
++ case IDEAPAD_WMI_EVENT_ESC:
++ ideapad_input_report(priv, 128);
++ break;
++ case IDEAPAD_WMI_EVENT_FN_KEYS:
++ if (priv->features.set_fn_lock_led &&
++ !eval_hals(priv->adev->handle, &result)) {
++ bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
++
++ exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
++ }
++
++ if (data->type != ACPI_TYPE_INTEGER) {
++ dev_warn(&wdev->dev,
++ "WMI event data is not an integer\n");
++ break;
++ }
++
++ dev_dbg(&wdev->dev, "WMI fn-key event: 0x%llx\n",
++ data->integer.value);
++
++ ideapad_input_report(priv,
++ data->integer.value | IDEAPAD_WMI_KEY);
++
++ break;
++ }
++unlock:
++ mutex_unlock(&ideapad_shared_mutex);
++}
++
++static const struct ideapad_wmi_private ideapad_wmi_context_esc = {
++ .event = IDEAPAD_WMI_EVENT_ESC
++};
++
++static const struct ideapad_wmi_private ideapad_wmi_context_fn_keys = {
++ .event = IDEAPAD_WMI_EVENT_FN_KEYS
++};
++
++static const struct wmi_device_id ideapad_wmi_ids[] = {
++ { "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", &ideapad_wmi_context_esc }, /* Yoga 3 */
++ { "56322276-8493-4CE8-A783-98C991274F5E", &ideapad_wmi_context_esc }, /* Yoga 700 */
++ { "8FC0DE0C-B4E4-43FD-B0F3-8871711C1294", &ideapad_wmi_context_fn_keys }, /* Legion 5 */
++ {},
++};
++MODULE_DEVICE_TABLE(wmi, ideapad_wmi_ids);
++
++static struct wmi_driver ideapad_wmi_driver = {
++ .driver = {
++ .name = "ideapad_wmi",
++ },
++ .id_table = ideapad_wmi_ids,
++ .probe = ideapad_wmi_probe,
++ .notify = ideapad_wmi_notify,
++};
++
++static int ideapad_wmi_driver_register(void)
++{
++ return wmi_driver_register(&ideapad_wmi_driver);
++}
++
++static void ideapad_wmi_driver_unregister(void)
++{
++ return wmi_driver_unregister(&ideapad_wmi_driver);
++}
++
++#else
++static inline int ideapad_wmi_driver_register(void) { return 0; }
++static inline void ideapad_wmi_driver_unregister(void) { }
++#endif
++
++/*
++ * ACPI driver
++ */
+ static int ideapad_acpi_add(struct platform_device *pdev)
+ {
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+@@ -1724,30 +1861,16 @@ static int ideapad_acpi_add(struct platform_device *pdev)
+ goto notification_failed;
+ }
+
+-#if IS_ENABLED(CONFIG_ACPI_WMI)
+- for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {
+- status = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],
+- ideapad_wmi_notify, priv);
+- if (ACPI_SUCCESS(status)) {
+- priv->fnesc_guid = ideapad_wmi_fnesc_events[i];
+- break;
+- }
+- }
+-
+- if (ACPI_FAILURE(status) && status != AE_NOT_EXIST) {
+- err = -EIO;
+- goto notification_failed_wmi;
+- }
+-#endif
++ err = ideapad_shared_init(priv);
++ if (err)
++ goto shared_init_failed;
+
+ return 0;
+
+-#if IS_ENABLED(CONFIG_ACPI_WMI)
+-notification_failed_wmi:
++shared_init_failed:
+ acpi_remove_notify_handler(priv->adev->handle,
+ ACPI_DEVICE_NOTIFY,
+ ideapad_acpi_notify);
+-#endif
+
+ notification_failed:
+ ideapad_backlight_exit(priv);
+@@ -1773,10 +1896,7 @@ static int ideapad_acpi_remove(struct platform_device *pdev)
+ struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
+ int i;
+
+-#if IS_ENABLED(CONFIG_ACPI_WMI)
+- if (priv->fnesc_guid)
+- wmi_remove_notify_handler(priv->fnesc_guid);
+-#endif
++ ideapad_shared_exit(priv);
+
+ acpi_remove_notify_handler(priv->adev->handle,
+ ACPI_DEVICE_NOTIFY,
+@@ -1828,7 +1948,30 @@ static struct platform_driver ideapad_acpi_driver = {
+ },
+ };
+
+-module_platform_driver(ideapad_acpi_driver);
++static int __init ideapad_laptop_init(void)
++{
++ int err;
++
++ err = ideapad_wmi_driver_register();
++ if (err)
++ return err;
++
++ err = platform_driver_register(&ideapad_acpi_driver);
++ if (err) {
++ ideapad_wmi_driver_unregister();
++ return err;
++ }
++
++ return 0;
++}
++module_init(ideapad_laptop_init)
++
++static void __exit ideapad_laptop_exit(void)
++{
++ ideapad_wmi_driver_unregister();
++ platform_driver_unregister(&ideapad_acpi_driver);
++}
++module_exit(ideapad_laptop_exit)
+
+ MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+ MODULE_DESCRIPTION("IdeaPad ACPI Extras");
+--
+2.35.1
+
--- /dev/null
+From 404bd4abd02dfda117af0b60755aacbd34a92228 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Nov 2022 09:00:14 +0200
+Subject: platform/x86: intel-uncore-freq: add Emerald Rapids support
+
+From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+
+[ Upstream commit 9c252ecf30360cb7b4dbcc275aebe5642174fd39 ]
+
+Make Intel uncore frequency driver support Emerald Rapids by adding its
+CPU model to the match table.
+
+Emerald Rapids uncore frequency control is the same as in Sapphire
+Rapids.
+
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Acked-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
+index 8f9c571d7257..00ac7e381441 100644
+--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
++++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
+@@ -203,6 +203,7 @@ static const struct x86_cpu_id intel_uncore_cpu_ids[] = {
+ X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, NULL),
++ X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, NULL),
+ {}
+ };
+ MODULE_DEVICE_TABLE(x86cpu, intel_uncore_cpu_ids);
+--
+2.35.1
+
--- /dev/null
+From fa058b0e9ff23bd4930c2545facd3a534e22597b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Nov 2022 13:43:22 +0100
+Subject: platform/x86: thinkpad_acpi: Fix max_brightness of thinklight
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit db5e2a4ca0a7a5fe54f410590292ea2e91de6798 ]
+
+Thinklight has only two values, on/off so it's reasonable for
+max_brightness to be 0 and 1 as if you write anything between 0 and 255
+it will be 255 anyway so there's no point for it to be 255.
+
+This may look like it is a userspace API change, but writes with
+a value larget then the new max_brightness will still be accepted,
+these will be silently clamped to the new max_brightness by
+led_set_brightness_nosleep(). So no userspace API problems are
+expected.
+
+Reported-by: MichaĆ Szczepaniak <m.szczepaniak.000@gmail.com>
+Link: https://lore.kernel.org/platform-driver-x86/55400326-e64f-5444-94e5-22b8214d00b6@gmail.com/
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/thinkpad_acpi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 8476dfef4e62..a1d91736a03b 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -5572,6 +5572,7 @@ static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
+ static struct tpacpi_led_classdev tpacpi_led_thinklight = {
+ .led_classdev = {
+ .name = "tpacpi::thinklight",
++ .max_brightness = 1,
+ .brightness_set_blocking = &light_sysfs_set,
+ .brightness_get = &light_sysfs_get,
+ }
+--
+2.35.1
+
--- /dev/null
+From 8a5b98ac26ba18faa55f4b4c791755779247bd8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Nov 2022 23:19:28 +0100
+Subject: platform/x86: x86-android-tablets: Add Advantech MICA-071 extra
+ button
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit b03ae77e7e057f4b3b858f10c840557e71448a91 ]
+
+The Advantech MICA-071 is a standard Windows tablet, but it has an extra
+"quick launch" button which is not described in the ACPI tables in anyway.
+
+Use the x86-android-tablets infra to create a gpio-button device for this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20221127221928.123660-1-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/x86-android-tablets.c | 58 ++++++++++++++++++++++
+ 1 file changed, 58 insertions(+)
+
+diff --git a/drivers/platform/x86/x86-android-tablets.c b/drivers/platform/x86/x86-android-tablets.c
+index bbfae1395e18..123a4618db55 100644
+--- a/drivers/platform/x86/x86-android-tablets.c
++++ b/drivers/platform/x86/x86-android-tablets.c
+@@ -265,6 +265,56 @@ static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = {
+ },
+ };
+
++/*
++ * Advantech MICA-071
++ * This is a standard Windows tablet, but it has an extra "quick launch" button
++ * which is not described in the ACPI tables in anyway.
++ * Use the x86-android-tablets infra to create a gpio-button device for this.
++ */
++static struct gpio_keys_button advantech_mica_071_button = {
++ .code = KEY_PROG1,
++ /* .gpio gets filled in by advantech_mica_071_init() */
++ .active_low = true,
++ .desc = "prog1_key",
++ .type = EV_KEY,
++ .wakeup = false,
++ .debounce_interval = 50,
++};
++
++static const struct gpio_keys_platform_data advantech_mica_071_button_pdata __initconst = {
++ .buttons = &advantech_mica_071_button,
++ .nbuttons = 1,
++ .name = "prog1_key",
++};
++
++static const struct platform_device_info advantech_mica_071_pdevs[] __initconst = {
++ {
++ .name = "gpio-keys",
++ .id = PLATFORM_DEVID_AUTO,
++ .data = &advantech_mica_071_button_pdata,
++ .size_data = sizeof(advantech_mica_071_button_pdata),
++ },
++};
++
++static int __init advantech_mica_071_init(void)
++{
++ struct gpio_desc *gpiod;
++ int ret;
++
++ ret = x86_android_tablet_get_gpiod("INT33FC:00", 2, &gpiod);
++ if (ret < 0)
++ return ret;
++ advantech_mica_071_button.gpio = desc_to_gpio(gpiod);
++
++ return 0;
++}
++
++static const struct x86_dev_info advantech_mica_071_info __initconst = {
++ .pdev_info = advantech_mica_071_pdevs,
++ .pdev_count = ARRAY_SIZE(advantech_mica_071_pdevs),
++ .init = advantech_mica_071_init,
++};
++
+ /* Asus ME176C and TF103C tablets shared data */
+ static struct gpio_keys_button asus_me176c_tf103c_lid = {
+ .code = SW_LID,
+@@ -1385,6 +1435,14 @@ static const struct x86_dev_info xiaomi_mipad2_info __initconst = {
+ };
+
+ static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
++ {
++ /* Advantech MICA-071 */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"),
++ },
++ .driver_data = (void *)&advantech_mica_071_info,
++ },
+ {
+ /* Asus MeMO Pad 7 ME176C */
+ .matches = {
+--
+2.35.1
+
--- /dev/null
+From 9c2fd2d81a45b7f1961f5a8f414c9b0229cb93b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Nov 2022 19:24:58 +0100
+Subject: platform/x86: x86-android-tablets: Add Lenovo Yoga Tab 3 (YT3-X90F)
+ charger + fuel-gauge data
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit b6c14ff1deaafd30036ec36d5205acd5a578b1cd ]
+
+The Lenovo Yoga Tab 3 (YT3-X90F) is an Intel Cherry Trail based tablet
+which ships with Android as Factory OS. Its DSDT contains a bunch of I2C
+devices which are not actually there, causing various resource conflicts.
+Use acpi_quirk_skip_i2c_client_enumeration() to not enumerate these.
+
+The YT3-X90F has quite a bit of exotic hardware, this adds initial
+support by manually instantiating the i2c-clients for the 2 charger +
+2 fuel-gauge chips used for the 2 batteries.
+
+Support for other parts of the hw will be added by follow-up patches.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20221127182458.104528-1-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/x86-android-tablets.c | 135 ++++++++++++++++++++-
+ 1 file changed, 134 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/x86-android-tablets.c b/drivers/platform/x86/x86-android-tablets.c
+index f04e06eeb958..bbfae1395e18 100644
+--- a/drivers/platform/x86/x86-android-tablets.c
++++ b/drivers/platform/x86/x86-android-tablets.c
+@@ -5,7 +5,7 @@
+ * devices typically have a bunch of things hardcoded, rather than specified
+ * in their DSDT.
+ *
+- * Copyright (C) 2021 Hans de Goede <hdegoede@redhat.com>
++ * Copyright (C) 2021-2022 Hans de Goede <hdegoede@redhat.com>
+ */
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+@@ -987,6 +987,130 @@ static void lenovo_yoga_tab2_830_1050_exit(void)
+ }
+ }
+
++/* Lenovo Yoga Tab 3 Pro YT3-X90F */
++
++/*
++ * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers,
++ * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c.
++ */
++static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
++static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
++
++static const struct property_entry fg_bq25890_1_supply_props[] = {
++ PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
++ { }
++};
++
++static const struct software_node fg_bq25890_1_supply_node = {
++ .properties = fg_bq25890_1_supply_props,
++};
++
++/* bq25892 charger settings for the flat lipo battery behind the screen */
++static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
++ PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
++ PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"),
++ PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
++ PROPERTY_ENTRY_BOOL("linux,skip-reset"),
++ /* Values taken from Android Factory Image */
++ PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
++ PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
++ PROPERTY_ENTRY_U32("ti,termination-current", 128000),
++ PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
++ PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
++ PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
++ PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
++ PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
++ { }
++};
++
++static const struct software_node lenovo_yt3_bq25892_0_node = {
++ .properties = lenovo_yt3_bq25892_0_props,
++};
++
++static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
++ {
++ /* bq27500 fuel-gauge for the flat lipo battery behind the screen */
++ .board_info = {
++ .type = "bq27500",
++ .addr = 0x55,
++ .dev_name = "bq27500_0",
++ .swnode = &fg_bq25890_supply_node,
++ },
++ .adapter_path = "\\_SB_.PCI0.I2C1",
++ }, {
++ /* bq25892 charger for the flat lipo battery behind the screen */
++ .board_info = {
++ .type = "bq25892",
++ .addr = 0x6b,
++ .dev_name = "bq25892_0",
++ .swnode = &lenovo_yt3_bq25892_0_node,
++ },
++ .adapter_path = "\\_SB_.PCI0.I2C1",
++ .irq_data = {
++ .type = X86_ACPI_IRQ_TYPE_GPIOINT,
++ .chip = "INT33FF:01",
++ .index = 5,
++ .trigger = ACPI_EDGE_SENSITIVE,
++ .polarity = ACPI_ACTIVE_LOW,
++ },
++ }, {
++ /* bq27500 fuel-gauge for the round li-ion cells in the hinge */
++ .board_info = {
++ .type = "bq27500",
++ .addr = 0x55,
++ .dev_name = "bq27500_1",
++ .swnode = &fg_bq25890_1_supply_node,
++ },
++ .adapter_path = "\\_SB_.PCI0.I2C2",
++ }
++};
++
++static int __init lenovo_yt3_init(void)
++{
++ struct gpio_desc *gpiod;
++ int ret;
++
++ /*
++ * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins
++ * connected to GPIOs, rather then having them hardwired to the correct
++ * values as is normally done.
++ *
++ * The bq25890_charger driver controls these through I2C, but this only
++ * works if not overridden by the pins. Set these pins here:
++ * 1. Set /CE to 0 to allow charging.
++ * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
++ * the main "bq25892_1" charger is used when necessary.
++ */
++
++ /* /CE pin */
++ ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod);
++ if (ret < 0)
++ return ret;
++
++ /*
++ * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw"
++ * gpio_desc, that is there is no way to pass lookup-flags like
++ * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since
++ * the /CE pin is active-low, but not marked as such in the gpio_desc.
++ */
++ gpiod_set_value(gpiod, 0);
++
++ /* OTG pin */
++ ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod);
++ if (ret < 0)
++ return ret;
++
++ gpiod_set_value(gpiod, 0);
++
++ return 0;
++}
++
++static const struct x86_dev_info lenovo_yt3_info __initconst = {
++ .i2c_client_info = lenovo_yt3_i2c_clients,
++ .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
++ .init = lenovo_yt3_init,
++};
++
+ /* Medion Lifetab S10346 tablets have an Android factory img with everything hardcoded */
+ static const char * const medion_lifetab_s10346_accel_mount_matrix[] = {
+ "0", "1", "0",
+@@ -1327,6 +1451,15 @@ static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
+ },
+ .driver_data = (void *)&lenovo_yoga_tab2_830_1050_info,
+ },
++ {
++ /* Lenovo Yoga Tab 3 Pro YT3-X90F */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
++ },
++ .driver_data = (void *)&lenovo_yt3_info,
++ },
+ {
+ /* Medion Lifetab S10346 */
+ .matches = {
+--
+2.35.1
+
--- /dev/null
+From 73285a3c7440b1b51116aa8df0a1b9ecccc44066 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 12:02:24 +0100
+Subject: platform/x86: x86-android-tablets: Add Medion Lifetab S10346 data
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 902ce18ab1f4444ff9d49865bea35a07adcc03fd ]
+
+The Medion Lifetab S10346 is a x86 ACPI tablet which ships with Android
+x86 as factory OS. Its DSDT contains a bunch of I2C devices which are not
+actually there, causing various resource conflicts. Enumeration of these
+is skipped through the acpi_quirk_skip_i2c_client_enumeration().
+
+Add support for manually instantiating the I2C devices which are
+actually present on this tablet by adding the necessary device info to
+the x86-android-tablets module.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Link: https://lore.kernel.org/r/20221208110224.107354-1-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/x86-android-tablets.c | 92 ++++++++++++++++++++++
+ 1 file changed, 92 insertions(+)
+
+diff --git a/drivers/platform/x86/x86-android-tablets.c b/drivers/platform/x86/x86-android-tablets.c
+index 4acd6fa8d43b..f04e06eeb958 100644
+--- a/drivers/platform/x86/x86-android-tablets.c
++++ b/drivers/platform/x86/x86-android-tablets.c
+@@ -987,6 +987,88 @@ static void lenovo_yoga_tab2_830_1050_exit(void)
+ }
+ }
+
++/* Medion Lifetab S10346 tablets have an Android factory img with everything hardcoded */
++static const char * const medion_lifetab_s10346_accel_mount_matrix[] = {
++ "0", "1", "0",
++ "1", "0", "0",
++ "0", "0", "1"
++};
++
++static const struct property_entry medion_lifetab_s10346_accel_props[] = {
++ PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", medion_lifetab_s10346_accel_mount_matrix),
++ { }
++};
++
++static const struct software_node medion_lifetab_s10346_accel_node = {
++ .properties = medion_lifetab_s10346_accel_props,
++};
++
++/* Note the LCD panel is mounted upside down, this is correctly indicated in the VBT */
++static const struct property_entry medion_lifetab_s10346_touchscreen_props[] = {
++ PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
++ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
++ { }
++};
++
++static const struct software_node medion_lifetab_s10346_touchscreen_node = {
++ .properties = medion_lifetab_s10346_touchscreen_props,
++};
++
++static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __initconst = {
++ {
++ /* kxtj21009 accel */
++ .board_info = {
++ .type = "kxtj21009",
++ .addr = 0x0f,
++ .dev_name = "kxtj21009",
++ .swnode = &medion_lifetab_s10346_accel_node,
++ },
++ .adapter_path = "\\_SB_.I2C3",
++ .irq_data = {
++ .type = X86_ACPI_IRQ_TYPE_GPIOINT,
++ .chip = "INT33FC:02",
++ .index = 23,
++ .trigger = ACPI_EDGE_SENSITIVE,
++ .polarity = ACPI_ACTIVE_HIGH,
++ },
++ }, {
++ /* goodix touchscreen */
++ .board_info = {
++ .type = "GDIX1001:00",
++ .addr = 0x14,
++ .dev_name = "goodix_ts",
++ .swnode = &medion_lifetab_s10346_touchscreen_node,
++ },
++ .adapter_path = "\\_SB_.I2C4",
++ .irq_data = {
++ .type = X86_ACPI_IRQ_TYPE_APIC,
++ .index = 0x44,
++ .trigger = ACPI_EDGE_SENSITIVE,
++ .polarity = ACPI_ACTIVE_LOW,
++ },
++ },
++};
++
++static struct gpiod_lookup_table medion_lifetab_s10346_goodix_gpios = {
++ .dev_id = "i2c-goodix_ts",
++ .table = {
++ GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("INT33FC:02", 3, "irq", GPIO_ACTIVE_HIGH),
++ { }
++ },
++};
++
++static struct gpiod_lookup_table * const medion_lifetab_s10346_gpios[] = {
++ &medion_lifetab_s10346_goodix_gpios,
++ NULL
++};
++
++static const struct x86_dev_info medion_lifetab_s10346_info __initconst = {
++ .i2c_client_info = medion_lifetab_s10346_i2c_clients,
++ .i2c_client_count = ARRAY_SIZE(medion_lifetab_s10346_i2c_clients),
++ .gpiod_lookup_tables = medion_lifetab_s10346_gpios,
++};
++
+ /* Nextbook Ares 8 tablets have an Android factory img with everything hardcoded */
+ static const char * const nextbook_ares8_accel_mount_matrix[] = {
+ "0", "-1", "0",
+@@ -1245,6 +1327,16 @@ static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
+ },
+ .driver_data = (void *)&lenovo_yoga_tab2_830_1050_info,
+ },
++ {
++ /* Medion Lifetab S10346 */
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
++ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
++ /* Above strings are much too generic, also match on BIOS date */
++ DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"),
++ },
++ .driver_data = (void *)&medion_lifetab_s10346_info,
++ },
+ {
+ /* Nextbook Ares 8 */
+ .matches = {
+--
+2.35.1
+
drm-amdgpu-skip-mes-for-s0ix-as-well-since-it-s-part-of-gfx.patch
drm-amdgpu-skip-mes-self-test-after-s0i3-resume-for-mes-ip-v11.0.patch
+bpf-resolve-fext-program-type-when-checking-map-comp.patch
+alsa-patch_realtek-fix-dell-inspiron-plus-16.patch
+alsa-hda-realtek-apply-dual-codec-fixup-for-dell-lat.patch
+platform-x86-thinkpad_acpi-fix-max_brightness-of-thi.patch
+platform-x86-ideapad-laptop-revert-check-for-touchpa.patch
+platform-x86-ideapad-laptop-add-new-_cfg-bit-numbers.patch
+platform-x86-ideapad-laptop-support-for-more-special.patch
+acpi-video-simplify-__acpi_video_get_backlight_type.patch
+acpi-video-prefer-native-over-vendor.patch
+platform-x86-ideapad-laptop-refactor-ideapad_sync_to.patch
+platform-x86-ideapad-laptop-do-not-send-key_touchpad.patch
+platform-x86-ideapad-laptop-only-toggle-ps2-aux-port.patch
+platform-x86-ideapad-laptop-send-key_touchpad_toggle.patch
+platform-x86-ideapad-laptop-stop-writing-vpccmd_w_to.patch
+platform-x86-intel-uncore-freq-add-emerald-rapids-su.patch
+alsa-hda-cirrus-add-extra-10-ms-delay-to-allow-pll-s.patch
+platform-x86-x86-android-tablets-add-medion-lifetab-.patch
+platform-x86-x86-android-tablets-add-lenovo-yoga-tab.patch
+platform-x86-x86-android-tablets-add-advantech-mica-.patch
+hid-ignore-hp-envy-x360-eu0009nv-stylus-battery.patch
+alsa-usb-audio-add-new-quirk-fixed_rate-for-jbl-quan.patch