Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Add bytcr-wm5102 to Fedora 33 kernel 5.10
From 976ca0414020562c2efdc56e6605d136a2ba6eb5 Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Sat, 6 Mar 2021 19:39:50 +0100
Subject: [PATCH] Compile with support for bytcr-wm5102
---
0001-WM5102.patch | 1105 +++++++++++++++++++++++++++++++++++++++
Patchlist | 1 +
filter-x86_64.sh | 4 +-
filter-x86_64.sh.fedora | 4 +-
kernel-local | 18 +
kernel.spec | 5 +-
6 files changed, 1134 insertions(+), 3 deletions(-)
create mode 100644 0001-WM5102.patch
diff --git a/0001-WM5102.patch b/0001-WM5102.patch
new file mode 100644
index 000000000..403aaa208
--- /dev/null
+++ b/0001-WM5102.patch
@@ -0,0 +1,1105 @@
+From 289037603a20b6cae158b34484d1d70be9a272c5 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 20 Jan 2021 22:49:53 +0100
+Subject: [PATCH 1/6] mfd: arizona: Add MODULE_SOFTDEP("pre: arizona_ldo1")
+
+The (shared) probing code of the arizona-i2c and arizona-spi modules
+takes the following steps during init:
+
+1. Call mfd_add_devices() for a set of early child-devices, this
+includes the arizona_ldo1 device which provides one of the
+core-regulators.
+
+2. Bulk enable the core-regulators.
+
+3. Read the device id.
+
+4. Call mfd_add_devices() for the other child-devices.
+
+This sequence depends on 1. leading to not only the child-device
+being created, but also the driver for the child-device binding
+to it and registering its regulator.
+
+This requires the arizona_ldo1 driver to be loaded before the
+shared probing code runs. Add a softdep for this to both modules to
+ensure that this requirement is met.
+
+Note this mirrors the existing MODULE_SOFTDEP("pre: wm8994_regulator")
+in the wm8994 code, which has a similar init sequence.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+---
+ drivers/mfd/arizona-i2c.c | 1 +
+ drivers/mfd/arizona-spi.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
+index 4b58e3ad6..2a4a3a164 100644
+--- a/drivers/mfd/arizona-i2c.c
++++ b/drivers/mfd/arizona-i2c.c
+@@ -115,6 +115,7 @@ static struct i2c_driver arizona_i2c_driver = {
+
+ module_i2c_driver(arizona_i2c_driver);
+
++MODULE_SOFTDEP("pre: arizona_ldo1");
+ MODULE_DESCRIPTION("Arizona I2C bus interface");
+ MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
+index 2633e147b..704f214d2 100644
+--- a/drivers/mfd/arizona-spi.c
++++ b/drivers/mfd/arizona-spi.c
+@@ -110,6 +110,7 @@ static struct spi_driver arizona_spi_driver = {
+
+ module_spi_driver(arizona_spi_driver);
+
++MODULE_SOFTDEP("pre: arizona_ldo1");
+ MODULE_DESCRIPTION("Arizona SPI bus interface");
+ MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+ MODULE_LICENSE("GPL");
+--
+2.29.2
+
+
+From 0ba03c22a853712f02f9dc98ba4829f12758856c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 20 Jan 2021 22:49:54 +0100
+Subject: [PATCH 2/6] mfd: arizona: Replace arizona_of_get_type() with
+ device_get_match_data()
+
+Replace the custom arizona_of_get_type() function with the generic
+device_get_match_data() helper. Besides being a nice cleanup this
+also makes it easier to add support for binding to ACPI enumerated
+devices.
+
+While at it also fix a possible NULL pointer deref of the id
+argument to the probe functions (this could happen on e.g. manual
+driver binding through sysfs).
+
+Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+---
+ drivers/mfd/arizona-core.c | 11 -----------
+ drivers/mfd/arizona-i2c.c | 10 ++++++----
+ drivers/mfd/arizona-spi.c | 10 ++++++----
+ drivers/mfd/arizona.h | 9 ---------
+ 4 files changed, 12 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
+index 000cb8202..75f1bc671 100644
+--- a/drivers/mfd/arizona-core.c
++++ b/drivers/mfd/arizona-core.c
+@@ -797,17 +797,6 @@ const struct dev_pm_ops arizona_pm_ops = {
+ EXPORT_SYMBOL_GPL(arizona_pm_ops);
+
+ #ifdef CONFIG_OF
+-unsigned long arizona_of_get_type(struct device *dev)
+-{
+- const struct of_device_id *id = of_match_device(arizona_of_match, dev);
+-
+- if (id)
+- return (unsigned long)id->data;
+- else
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(arizona_of_get_type);
+-
+ static int arizona_of_get_core_pdata(struct arizona *arizona)
+ {
+ struct arizona_pdata *pdata = &arizona->pdata;
+diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
+index 2a4a3a164..5e83b730c 100644
+--- a/drivers/mfd/arizona-i2c.c
++++ b/drivers/mfd/arizona-i2c.c
+@@ -23,14 +23,16 @@
+ static int arizona_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+ {
++ const void *match_data;
+ struct arizona *arizona;
+ const struct regmap_config *regmap_config = NULL;
+- unsigned long type;
++ unsigned long type = 0;
+ int ret;
+
+- if (i2c->dev.of_node)
+- type = arizona_of_get_type(&i2c->dev);
+- else
++ match_data = device_get_match_data(&i2c->dev);
++ if (match_data)
++ type = (unsigned long)match_data;
++ else if (id)
+ type = id->driver_data;
+
+ switch (type) {
+diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
+index 704f214d2..798b88295 100644
+--- a/drivers/mfd/arizona-spi.c
++++ b/drivers/mfd/arizona-spi.c
+@@ -23,14 +23,16 @@
+ static int arizona_spi_probe(struct spi_device *spi)
+ {
+ const struct spi_device_id *id = spi_get_device_id(spi);
++ const void *match_data;
+ struct arizona *arizona;
+ const struct regmap_config *regmap_config = NULL;
+- unsigned long type;
++ unsigned long type = 0;
+ int ret;
+
+- if (spi->dev.of_node)
+- type = arizona_of_get_type(&spi->dev);
+- else
++ match_data = device_get_match_data(&spi->dev);
++ if (match_data)
++ type = (unsigned long)match_data;
++ else if (id)
+ type = id->driver_data;
+
+ switch (type) {
+diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h
+index 995efc6d7..801cbbcd7 100644
+--- a/drivers/mfd/arizona.h
++++ b/drivers/mfd/arizona.h
+@@ -50,13 +50,4 @@ int arizona_dev_exit(struct arizona *arizona);
+ int arizona_irq_init(struct arizona *arizona);
+ int arizona_irq_exit(struct arizona *arizona);
+
+-#ifdef CONFIG_OF
+-unsigned long arizona_of_get_type(struct device *dev);
+-#else
+-static inline unsigned long arizona_of_get_type(struct device *dev)
+-{
+- return 0;
+-}
+-#endif
+-
+ #endif
+--
+2.29.2
+
+
+From f426a51814e5ce9e6a87cd283d577e9e9eee5e5d Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 20 Jan 2021 22:49:55 +0100
+Subject: [PATCH 3/6] mfd: arizona: Add support for ACPI enumeration of WM5102
+ connected over SPI
+
+The Intel Bay Trail (x86/ACPI) based Lenovo Yoga Tablet 2 series use
+a WM5102 codec connected over SPI.
+
+Add support for ACPI enumeration to arizona-spi so that arizona-spi can
+bind to the codec on these tablets.
+
+This is loosely based on an earlier attempt (for Android-x86) at this by
+Christian Hartmann, combined with insights in things like the speaker GPIO
+from the android-x86 android port for the Lenovo Yoga Tablet 2 1051F/L [1].
+
+[1] https://github.com/Kitsune2222/Android_Yoga_Tablet_2-1051F_Kernel
+
+Cc: Christian Hartmann <cornogle@googlemail.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+---
+ drivers/mfd/arizona-spi.c | 127 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 127 insertions(+)
+
+diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
+index 798b88295..24a2c75d6 100644
+--- a/drivers/mfd/arizona-spi.c
++++ b/drivers/mfd/arizona-spi.c
+@@ -7,7 +7,10 @@
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ */
+
++#include <linux/acpi.h>
+ #include <linux/err.h>
++#include <linux/gpio/consumer.h>
++#include <linux/gpio/machine.h>
+ #include <linux/module.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regmap.h>
+@@ -15,11 +18,128 @@
+ #include <linux/slab.h>
+ #include <linux/spi/spi.h>
+ #include <linux/of.h>
++#include <uapi/linux/input-event-codes.h>
+
+ #include <linux/mfd/arizona/core.h>
+
+ #include "arizona.h"
+
++#ifdef CONFIG_ACPI
++const struct acpi_gpio_params reset_gpios = { 1, 0, false };
++const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
++
++static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
++ { "reset-gpios", &reset_gpios, 1, },
++ { "wlf,ldoena-gpios", &ldoena_gpios, 1 },
++ { }
++};
++
++/*
++ * The ACPI resources for the device only describe external GPIO-s. They do
++ * not provide mappings for the GPIO-s coming from the Arizona codec itself.
++ */
++static const struct gpiod_lookup arizona_soc_gpios[] = {
++ { "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
++ { "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
++};
++
++/*
++ * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
++ * Function A Play/Pause: 0 ohm
++ * Function D Voice assistant: 135 ohm
++ * Function B Volume Up 240 ohm
++ * Function C Volume Down 470 ohm
++ * Minimum Mic DC resistance 1000 ohm
++ * Minimum Ear speaker impedance 16 ohm
++ * Note the first max value below must be less then the min. speaker impedance,
++ * to allow CTIA/OMTP detection to work. The other max values are the closest
++ * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
++ */
++static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
++ { .max = 11, .key = KEY_PLAYPAUSE },
++ { .max = 186, .key = KEY_VOICECOMMAND },
++ { .max = 348, .key = KEY_VOLUMEUP },
++ { .max = 752, .key = KEY_VOLUMEDOWN },
++};
++
++static void arizona_spi_acpi_remove_lookup(void *lookup)
++{
++ gpiod_remove_lookup_table(lookup);
++}
++
++static int arizona_spi_acpi_probe(struct arizona *arizona)
++{
++ struct gpiod_lookup_table *lookup;
++ acpi_status status;
++ int ret;
++
++ /* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
++ devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
++
++ /* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
++ lookup = devm_kzalloc(arizona->dev,
++ struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
++ GFP_KERNEL);
++ if (!lookup)
++ return -ENOMEM;
++
++ lookup->dev_id = dev_name(arizona->dev);
++ memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
++
++ gpiod_add_lookup_table(lookup);
++ ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
++ if (ret)
++ return ret;
++
++ /* Enable 32KHz clock from SoC to codec for jack-detect */
++ status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
++ if (ACPI_FAILURE(status))
++ dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
++
++ /*
++ * Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
++ * The IRQ line will stay low when a new IRQ event happens between reading
++ * the IRQ status flags and acknowledging them. When the IRQ line stays
++ * low like this the IRQ will never trigger again when its type is set
++ * to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
++ *
++ * Note theoretically it is possible that some boards are not capable
++ * of handling active low level interrupts. In that case setting the
++ * flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
++ * to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
++ * are a bug in the board's DSDT.
++ */
++ arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
++
++ /* Wait 200 ms after jack insertion */
++ arizona->pdata.micd_detect_debounce = 200;
++
++ /* Use standard AOSP values for headset-button mappings */
++ arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
++ arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
++
++ return 0;
++}
++
++static const struct acpi_device_id arizona_acpi_match[] = {
++ {
++ .id = "WM510204",
++ .driver_data = WM5102,
++ },
++ {
++ .id = "WM510205",
++ .driver_data = WM5102,
++ },
++ { }
++};
++MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
++#else
++static int arizona_spi_acpi_probe(struct arizona *arizona)
++{
++ return -ENODEV;
++}
++#endif
++
+ static int arizona_spi_probe(struct spi_device *spi)
+ {
+ const struct spi_device_id *id = spi_get_device_id(spi);
+@@ -77,6 +197,12 @@ static int arizona_spi_probe(struct spi_device *spi)
+ arizona->dev = &spi->dev;
+ arizona->irq = spi->irq;
+
++ if (has_acpi_companion(&spi->dev)) {
++ ret = arizona_spi_acpi_probe(arizona);
++ if (ret)
++ return ret;
++ }
++
+ return arizona_dev_init(arizona);
+ }
+
+@@ -104,6 +230,7 @@ static struct spi_driver arizona_spi_driver = {
+ .name = "arizona",
+ .pm = &arizona_pm_ops,
+ .of_match_table = of_match_ptr(arizona_of_match),
++ .acpi_match_table = ACPI_PTR(arizona_acpi_match),
+ },
+ .probe = arizona_spi_probe,
+ .remove = arizona_spi_remove,
+--
+2.29.2
+
+
+From eb1c76ac7aa0c81e876a83e1afbf54f7256be3a8 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 20 Jan 2021 22:49:56 +0100
+Subject: [PATCH 4/6] ASoC: Intel: Add DMI quirk table to soc_intel_is_byt_cr()
+
+Some Bay Trail systems:
+1. Use a non CR version of the Bay Trail SoC
+2. Contain at least 6 interrupt resources so that the
+ platform_get_resource(pdev, IORESOURCE_IRQ, 5) check to workaround
+ non CR systems which list their IPC IRQ at index 0 despite being
+ non CR does not work
+3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5
+
+Add a DMI quirk table to check for the few known models with this issue,
+so that the right IPC IRQ index is used on these systems.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20210120214957.140232-5-hdegoede@redhat.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/intel/common/soc-intel-quirks.h | 25 +++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/sound/soc/intel/common/soc-intel-quirks.h b/sound/soc/intel/common/soc-intel-quirks.h
+index b07df3059..a93987ab7 100644
+--- a/sound/soc/intel/common/soc-intel-quirks.h
++++ b/sound/soc/intel/common/soc-intel-quirks.h
+@@ -11,6 +11,7 @@
+
+ #if IS_ENABLED(CONFIG_X86)
+
++#include <linux/dmi.h>
+ #include <asm/cpu_device_id.h>
+ #include <asm/intel-family.h>
+ #include <asm/iosf_mbi.h>
+@@ -38,12 +39,36 @@ SOC_INTEL_IS_CPU(cml, KABYLAKE_L);
+
+ static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
+ {
++ /*
++ * List of systems which:
++ * 1. Use a non CR version of the Bay Trail SoC
++ * 2. Contain at least 6 interrupt resources so that the
++ * platform_get_resource(pdev, IORESOURCE_IRQ, 5) check below
++ * succeeds
++ * 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5
++ *
++ * This needs to be here so that it can be shared between the SST and
++ * SOF drivers. We rely on the compiler to optimize this out in files
++ * where soc_intel_is_byt_cr is not used.
++ */
++ static const struct dmi_system_id force_bytcr_table[] = {
++ { /* Lenovo Yoga Tablet 2 series */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"),
++ },
++ },
++ {}
++ };
+ struct device *dev = &pdev->dev;
+ int status = 0;
+
+ if (!soc_intel_is_byt())
+ return false;
+
++ if (dmi_check_system(force_bytcr_table))
++ return true;
++
+ if (iosf_mbi_available()) {
+ u32 bios_status;
+
+--
+2.29.2
+
+
+From 92b3356a7e2cc1f31a75f9e4f9e223d68aabfd42 Mon Sep 17 00:00:00 2001
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Date: Wed, 20 Jan 2021 22:49:57 +0100
+Subject: [PATCH 5/6] ASoC: Intel: bytcr_wm5102: Add machine driver for
+ BYT/WM5102
+
+Add a new ASoc Machine driver for Intel Baytrail platforms with a
+Wolfson Microelectronics WM5102 codec.
+
+This is based on a past contributions [1] from Paulo Sergio Travaglia
+<pstglia@gmail.com> based on the Levono kernel [2] combined with
+insights in things like the speaker GPIO from the android-x86 android
+port for the Lenovo Yoga Tablet 2 1051F/L [3].
+
+[1] https://patchwork.kernel.org/project/alsa-devel/patch/593313f5.3636c80a.50e05.47e9@mx.google.com/
+[2] https://github.com/lenovo-yt2-dev/android_kernel_lenovo_baytrail/blob/cm-12.1/sound/soc/intel/board/byt_bl_wm5102.c
+[3] https://github.com/Kitsune2222/Android_Yoga_Tablet_2-1051F_Kernel
+
+The original machine driver from the Android ports was a crude modified
+copy of bytcr_rt5640.c adjusted to work with the WM5102 codec.
+This version has been extensively reworked to:
+
+1. Remove all rt5640 related quirk handling. to the best of my knowledge
+this setup is only used on the Lenovo Yoga Tablet 2 series (8, 10 and 13
+inch models) which all use the same setup. So there is no need to deal
+with all the variations with which we need to deal on rt5640 boards.
+
+2. Rework clock handling, properly turn off the FLL and the platform-clock
+when they are no longer necessary and don't reconfigure the FLL
+unnecessarily when it is already running. This fixes a number of:
+"Timed out waiting for lock" warnings being logged.
+
+3. Add the GPIO controlled Speaker-VDD regulator as a DAPM_SUPPLY
+
+This only adds the machine driver and ACPI hooks, the BYT-CR detection
+quirk which these devices need will be added in a separate patch.
+
+BugLink: https://github.com/thesofproject/linux/issues/2485
+Co-authored-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20210120214957.140232-6-hdegoede@redhat.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ sound/soc/intel/boards/Kconfig | 12 +
+ sound/soc/intel/boards/Makefile | 2 +
+ sound/soc/intel/boards/bytcr_wm5102.c | 465 ++++++++++++++++++
+ .../intel/common/soc-acpi-intel-byt-match.c | 16 +
+ 4 files changed, 495 insertions(+)
+ create mode 100644 sound/soc/intel/boards/bytcr_wm5102.c
+
+diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
+index c10c37803..6ce04b648 100644
+--- a/sound/soc/intel/boards/Kconfig
++++ b/sound/soc/intel/boards/Kconfig
+@@ -111,6 +111,18 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH
+ Say Y or m if you have such a device. This is a recommended option.
+ If unsure select "N".
+
++config SND_SOC_INTEL_BYTCR_WM5102_MACH
++ tristate "Baytrail and Baytrail-CR with WM5102 codec"
++ depends on MFD_ARIZONA && MFD_WM5102 && SPI_MASTER && ACPI
++ depends on X86_INTEL_LPSS || COMPILE_TEST
++ select SND_SOC_ACPI
++ select SND_SOC_WM5102
++ help
++ This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
++ platforms with WM5102 audio codec.
++ Say Y if you have such a device.
++ If unsure select "N".
++
+ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
+ tristate "Cherrytrail & Braswell with RT5672 codec"
+ depends on I2C && ACPI
+diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
+index a58e4d22e..86661357b 100644
+--- a/sound/soc/intel/boards/Makefile
++++ b/sound/soc/intel/boards/Makefile
+@@ -10,6 +10,7 @@ snd-soc-sst-sof-wm8804-objs := sof_wm8804.o
+ snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o
+ snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
+ snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
++snd-soc-sst-bytcr-wm5102-objs := bytcr_wm5102.o
+ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
+ snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
+ snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
+@@ -51,6 +52,7 @@ obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o
+ obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o
+ obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
+ obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH) += snd-soc-sst-bytcr-rt5651.o
++obj-$(CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH) += snd-soc-sst-bytcr-wm5102.o
+ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
+ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
+ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
+diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c
+new file mode 100644
+index 000000000..f38850eb2
+--- /dev/null
++++ b/sound/soc/intel/boards/bytcr_wm5102.c
+@@ -0,0 +1,465 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * bytcr_wm5102.c - ASoc Machine driver for Intel Baytrail platforms with a
++ * Wolfson Microelectronics WM5102 codec
++ *
++ * Copyright (C) 2020 Hans de Goede <hdegoede@redhat.com>
++ * Loosely based on bytcr_rt5640.c which is:
++ * Copyright (C) 2014-2020 Intel Corp
++ * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
++ */
++
++#include <linux/acpi.h>
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/spi/spi.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-acpi.h>
++#include "../../codecs/wm5102.h"
++#include "../atom/sst-atom-controls.h"
++
++#define MCLK_FREQ 25000000
++
++#define WM5102_MAX_SYSCLK_4K 49152000 /* max sysclk for 4K family */
++#define WM5102_MAX_SYSCLK_11025 45158400 /* max sysclk for 11.025K family */
++
++struct byt_wm5102_private {
++ struct clk *mclk;
++ struct gpio_desc *spkvdd_en_gpio;
++};
++
++static int byt_wm5102_spkvdd_power_event(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *kcontrol, int event)
++{
++ struct snd_soc_card *card = w->dapm->card;
++ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
++
++ gpiod_set_value_cansleep(priv->spkvdd_en_gpio,
++ !!SND_SOC_DAPM_EVENT_ON(event));
++
++ return 0;
++}
++
++static int byt_wm5102_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, int rate)
++{
++ struct snd_soc_component *codec_component = codec_dai->component;
++ int sr_mult = ((rate % 4000) == 0) ?
++ (WM5102_MAX_SYSCLK_4K / rate) :
++ (WM5102_MAX_SYSCLK_11025 / rate);
++ int ret;
++
++ /* Reset FLL1 */
++ snd_soc_dai_set_pll(codec_dai, WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0);
++ snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
++
++ /* Configure the FLL1 PLL before selecting it */
++ ret = snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_CLK_SRC_MCLK1,
++ MCLK_FREQ, rate * sr_mult);
++ if (ret) {
++ dev_err(codec_component->dev, "Error setting PLL: %d\n", ret);
++ return ret;
++ }
++
++ ret = snd_soc_component_set_sysclk(codec_component, ARIZONA_CLK_SYSCLK,
++ ARIZONA_CLK_SRC_FLL1, rate * sr_mult,
++ SND_SOC_CLOCK_IN);
++ if (ret) {
++ dev_err(codec_component->dev, "Error setting SYSCLK: %d\n", ret);
++ return ret;
++ }
++
++ ret = snd_soc_dai_set_sysclk(codec_dai, ARIZONA_CLK_SYSCLK,
++ rate * 512, SND_SOC_CLOCK_IN);
++ if (ret) {
++ dev_err(codec_component->dev, "Error setting clock: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int platform_clock_control(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *k, int event)
++{
++ struct snd_soc_dapm_context *dapm = w->dapm;
++ struct snd_soc_card *card = dapm->card;
++ struct snd_soc_dai *codec_dai;
++ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
++ int ret;
++
++ codec_dai = snd_soc_card_get_codec_dai(card, "wm5102-aif1");
++ if (!codec_dai) {
++ dev_err(card->dev, "Error codec DAI not found\n");
++ return -EIO;
++ }
++
++ if (SND_SOC_DAPM_EVENT_ON(event)) {
++ ret = clk_prepare_enable(priv->mclk);
++ if (ret) {
++ dev_err(card->dev, "Error enabling MCLK: %d\n", ret);
++ return ret;
++ }
++ ret = byt_wm5102_prepare_and_enable_pll1(codec_dai, 48000);
++ if (ret) {
++ dev_err(card->dev, "Error setting codec sysclk: %d\n", ret);
++ return ret;
++ }
++ } else {
++ /*
++ * The WM5102 has a separate 32KHz clock for jack-detect
++ * so we can disable the PLL, followed by disabling the
++ * platform clock which is the source-clock for the PLL.
++ */
++ snd_soc_dai_set_pll(codec_dai, WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
++ clk_disable_unprepare(priv->mclk);
++ }
++
++ return 0;
++}
++
++static const struct snd_soc_dapm_widget byt_wm5102_widgets[] = {
++ SND_SOC_DAPM_HP("Headphone", NULL),
++ SND_SOC_DAPM_MIC("Headset Mic", NULL),
++ SND_SOC_DAPM_MIC("Internal Mic", NULL),
++ SND_SOC_DAPM_SPK("Speaker", NULL),
++ SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
++ platform_clock_control, SND_SOC_DAPM_PRE_PMU |
++ SND_SOC_DAPM_POST_PMD),
++ SND_SOC_DAPM_SUPPLY("Speaker VDD", SND_SOC_NOPM, 0, 0,
++ byt_wm5102_spkvdd_power_event,
++ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
++};
++
++static const struct snd_soc_dapm_route byt_wm5102_audio_map[] = {
++ {"Headphone", NULL, "Platform Clock"},
++ {"Headset Mic", NULL, "Platform Clock"},
++ {"Internal Mic", NULL, "Platform Clock"},
++ {"Speaker", NULL, "Platform Clock"},
++
++ {"Speaker", NULL, "SPKOUTLP"},
++ {"Speaker", NULL, "SPKOUTLN"},
++ {"Speaker", NULL, "SPKOUTRP"},
++ {"Speaker", NULL, "SPKOUTRN"},
++ {"Speaker", NULL, "Speaker VDD"},
++
++ {"Headphone", NULL, "HPOUT1L"},
++ {"Headphone", NULL, "HPOUT1R"},
++
++ {"Internal Mic", NULL, "MICBIAS3"},
++ {"IN3L", NULL, "Internal Mic"},
++
++ /*
++ * The Headset Mix uses MICBIAS1 or 2 depending on if a CTIA/OMTP Headset
++ * is connected, as the MICBIAS is applied after the CTIA/OMTP cross-switch.
++ */
++ {"Headset Mic", NULL, "MICBIAS1"},
++ {"Headset Mic", NULL, "MICBIAS2"},
++ {"IN1L", NULL, "Headset Mic"},
++
++ {"AIF1 Playback", NULL, "ssp0 Tx"},
++ {"ssp0 Tx", NULL, "modem_out"},
++
++ {"modem_in", NULL, "ssp0 Rx"},
++ {"ssp0 Rx", NULL, "AIF1 Capture"},
++};
++
++static const struct snd_kcontrol_new byt_wm5102_controls[] = {
++ SOC_DAPM_PIN_SWITCH("Headphone"),
++ SOC_DAPM_PIN_SWITCH("Headset Mic"),
++ SOC_DAPM_PIN_SWITCH("Internal Mic"),
++ SOC_DAPM_PIN_SWITCH("Speaker"),
++};
++
++static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
++ int ret;
++
++ card->dapm.idle_bias_off = true;
++
++ ret = snd_soc_add_card_controls(card, byt_wm5102_controls,
++ ARRAY_SIZE(byt_wm5102_controls));
++ if (ret) {
++ dev_err(card->dev, "Error adding card controls: %d\n", ret);
++ return ret;
++ }
++
++ /*
++ * The firmware might enable the clock at boot (this information
++ * may or may not be reflected in the enable clock register).
++ * To change the rate we must disable the clock first to cover these
++ * cases. Due to common clock framework restrictions that do not allow
++ * to disable a clock that has not been enabled, we need to enable
++ * the clock first.
++ */
++ ret = clk_prepare_enable(priv->mclk);
++ if (!ret)
++ clk_disable_unprepare(priv->mclk);
++
++ ret = clk_set_rate(priv->mclk, MCLK_FREQ);
++ if (ret) {
++ dev_err(card->dev, "Error setting MCLK rate: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static const struct snd_soc_pcm_stream byt_wm5102_dai_params = {
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .rate_min = 48000,
++ .rate_max = 48000,
++ .channels_min = 2,
++ .channels_max = 2,
++};
++
++static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_interval *rate = hw_param_interval(params,
++ SNDRV_PCM_HW_PARAM_RATE);
++ struct snd_interval *channels = hw_param_interval(params,
++ SNDRV_PCM_HW_PARAM_CHANNELS);
++ int ret;
++
++ /* The DSP will covert the FE rate to 48k, stereo */
++ rate->min = 48000;
++ rate->max = 48000;
++ channels->min = 2;
++ channels->max = 2;
++
++ /* set SSP0 to 16-bit */
++ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
++
++ /*
++ * Default mode for SSP configuration is TDM 4 slot, override config
++ * with explicit setting to I2S 2ch 16-bit. The word length is set with
++ * dai_set_tdm_slot() since there is no other API exposed
++ */
++ ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
++ SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBS_CFS);
++ if (ret) {
++ dev_err(rtd->dev, "Error setting format to I2S: %d\n", ret);
++ return ret;
++ }
++
++ ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16);
++ if (ret) {
++ dev_err(rtd->dev, "Error setting I2S config: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int byt_wm5102_aif1_startup(struct snd_pcm_substream *substream)
++{
++ return snd_pcm_hw_constraint_single(substream->runtime,
++ SNDRV_PCM_HW_PARAM_RATE, 48000);
++}
++
++static const struct snd_soc_ops byt_wm5102_aif1_ops = {
++ .startup = byt_wm5102_aif1_startup,
++};
++
++SND_SOC_DAILINK_DEF(dummy,
++ DAILINK_COMP_ARRAY(COMP_DUMMY()));
++
++SND_SOC_DAILINK_DEF(media,
++ DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
++
++SND_SOC_DAILINK_DEF(deepbuffer,
++ DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
++
++SND_SOC_DAILINK_DEF(ssp0_port,
++ DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port")));
++
++SND_SOC_DAILINK_DEF(ssp0_codec,
++ DAILINK_COMP_ARRAY(COMP_CODEC(
++ /*
++ * Note there is no need to overwrite the codec-name as is done in
++ * other bytcr machine drivers, because the codec is a MFD child-dev.
++ */
++ "wm5102-codec",
++ "wm5102-aif1")));
++
++SND_SOC_DAILINK_DEF(platform,
++ DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
++
++static struct snd_soc_dai_link byt_wm5102_dais[] = {
++ [MERR_DPCM_AUDIO] = {
++ .name = "Baytrail Audio Port",
++ .stream_name = "Baytrail Audio",
++ .nonatomic = true,
++ .dynamic = 1,
++ .dpcm_playback = 1,
++ .dpcm_capture = 1,
++ .ops = &byt_wm5102_aif1_ops,
++ SND_SOC_DAILINK_REG(media, dummy, platform),
++
++ },
++ [MERR_DPCM_DEEP_BUFFER] = {
++ .name = "Deep-Buffer Audio Port",
++ .stream_name = "Deep-Buffer Audio",
++ .nonatomic = true,
++ .dynamic = 1,
++ .dpcm_playback = 1,
++ .ops = &byt_wm5102_aif1_ops,
++ SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
++ },
++ /* back ends */
++ {
++ /*
++ * This must be named SSP2-Codec even though this machine driver
++ * always uses SSP0. Most machine drivers support both and dynamically
++ * update the dailink to point to SSP0 or SSP2, while keeping the name
++ * as "SSP2-Codec". The SOF tplg files hardcode the "SSP2-Codec" even
++ * in the byt-foo-ssp0.tplg versions because the other machine-drivers
++ * use "SSP2-Codec" even when SSP0 is used.
++ */
++ .name = "SSP2-Codec",
++ .id = 0,
++ .no_pcm = 1,
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBS_CFS,
++ .be_hw_params_fixup = byt_wm5102_codec_fixup,
++ .nonatomic = true,
++ .dpcm_playback = 1,
++ .dpcm_capture = 1,
++ .init = byt_wm5102_init,
++ SND_SOC_DAILINK_REG(ssp0_port, ssp0_codec, platform),
++ },
++};
++
++/* use space before codec name to simplify card ID, and simplify driver name */
++#define SOF_CARD_NAME "bytcht wm5102" /* card name will be 'sof-bytcht wm5102' */
++#define SOF_DRIVER_NAME "SOF"
++
++#define CARD_NAME "bytcr-wm5102"
++#define DRIVER_NAME NULL /* card name will be used for driver name */
++
++/* SoC card */
++static struct snd_soc_card byt_wm5102_card = {
++ .owner = THIS_MODULE,
++ .dai_link = byt_wm5102_dais,
++ .num_links = ARRAY_SIZE(byt_wm5102_dais),
++ .dapm_widgets = byt_wm5102_widgets,
++ .num_dapm_widgets = ARRAY_SIZE(byt_wm5102_widgets),
++ .dapm_routes = byt_wm5102_audio_map,
++ .num_dapm_routes = ARRAY_SIZE(byt_wm5102_audio_map),
++ .fully_routed = true,
++};
++
++static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
++{
++ char codec_name[SND_ACPI_I2C_ID_LEN];
++ struct device *dev = &pdev->dev;
++ struct byt_wm5102_private *priv;
++ struct snd_soc_acpi_mach *mach;
++ const char *platform_name;
++ struct acpi_device *adev;
++ struct device *codec_dev;
++ bool sof_parent;
++ int ret;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_ATOMIC);
++ if (!priv)
++ return -ENOMEM;
++
++ /* Get MCLK */
++ priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
++ if (IS_ERR(priv->mclk))
++ return dev_err_probe(dev, PTR_ERR(priv->mclk), "getting pmc_plt_clk_3\n");
++
++ /*
++ * Get speaker VDD enable GPIO:
++ * 1. Get codec-device-name
++ * 2. Get codec-device
++ * 3. Get GPIO from codec-device
++ */
++ mach = dev->platform_data;
++ adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
++ if (!adev) {
++ dev_err(dev, "Error cannot find acpi-dev for codec\n");
++ return -ENOENT;
++ }
++ snprintf(codec_name, sizeof(codec_name), "spi-%s", acpi_dev_name(adev));
++ put_device(&adev->dev);
++
++ codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name);
++ if (!codec_dev)
++ return -EPROBE_DEFER;
++
++ /* Note no devm_ here since we call gpiod_get on codec_dev rather then dev */
++ priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW);
++ put_device(codec_dev);
++
++ if (IS_ERR(priv->spkvdd_en_gpio))
++ return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n");
++
++ /* override platform name, if required */
++ byt_wm5102_card.dev = dev;
++ platform_name = mach->mach_params.platform;
++ ret = snd_soc_fixup_dai_links_platform_name(&byt_wm5102_card, platform_name);
++ if (ret)
++ goto out_put_gpio;
++
++ /* set card and driver name and pm-ops */
++ sof_parent = snd_soc_acpi_sof_parent(dev);
++ if (sof_parent) {
++ byt_wm5102_card.name = SOF_CARD_NAME;
++ byt_wm5102_card.driver_name = SOF_DRIVER_NAME;
++ dev->driver->pm = &snd_soc_pm_ops;
++ } else {
++ byt_wm5102_card.name = CARD_NAME;
++ byt_wm5102_card.driver_name = DRIVER_NAME;
++ }
++
++ snd_soc_card_set_drvdata(&byt_wm5102_card, priv);
++ ret = devm_snd_soc_register_card(dev, &byt_wm5102_card);
++ if (ret) {
++ dev_err_probe(dev, ret, "registering card\n");
++ goto out_put_gpio;
++ }
++
++ platform_set_drvdata(pdev, &byt_wm5102_card);
++ return 0;
++
++out_put_gpio:
++ gpiod_put(priv->spkvdd_en_gpio);
++ return ret;
++}
++
++static int snd_byt_wm5102_mc_remove(struct platform_device *pdev)
++{
++ struct snd_soc_card *card = platform_get_drvdata(pdev);
++ struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card);
++
++ gpiod_put(priv->spkvdd_en_gpio);
++ return 0;
++}
++
++static struct platform_driver snd_byt_wm5102_mc_driver = {
++ .driver = {
++ .name = "bytcr_wm5102",
++ },
++ .probe = snd_byt_wm5102_mc_probe,
++ .remove = snd_byt_wm5102_mc_remove,
++};
++
++module_platform_driver(snd_byt_wm5102_mc_driver);
++
++MODULE_DESCRIPTION("ASoC Baytrail with WM5102 codec machine driver");
++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:bytcr_wm5102");
+diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
+index c348607b4..ec7932549 100644
+--- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c
++++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
+@@ -154,6 +154,22 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[] = {
+ .sof_fw_filename = "sof-byt.ri",
+ .sof_tplg_filename = "sof-byt-rt5651.tplg",
+ },
++ {
++ .id = "WM510204",
++ .drv_name = "bytcr_wm5102",
++ .fw_filename = "intel/fw_sst_0f28.bin",
++ .board = "bytcr_wm5102",
++ .sof_fw_filename = "sof-byt.ri",
++ .sof_tplg_filename = "sof-byt-wm5102.tplg",
++ },
++ {
++ .id = "WM510205",
++ .drv_name = "bytcr_wm5102",
++ .fw_filename = "intel/fw_sst_0f28.bin",
++ .board = "bytcr_wm5102",
++ .sof_fw_filename = "sof-byt.ri",
++ .sof_tplg_filename = "sof-byt-wm5102.tplg",
++ },
+ {
+ .id = "DLGS7212",
+ .drv_name = "bytcht_da7213",
+--
+2.29.2
+
+
+From c118900dff8d1dc0fbee69048d12e3554efd7e89 Mon Sep 17 00:00:00 2001
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Date: Thu, 12 Nov 2020 16:38:15 -0600
+Subject: [PATCH 6/6] ASoC: soc-acpi: add helper to identify parent driver.
+
+Intel machine drivers are used by parent platform drivers based on
+closed-source firmware (Atom/SST and catpt) and SOF-based ones.
+
+In some cases for ACPI-based platforms, the behavior of machine
+drivers needs to be modified depending on the parent type, typically
+for card names and power management.
+
+An initial solution based on passing a boolean flag as a platform
+device parameter was tested earlier. Since it looked overkill, this
+patch suggests instead a simple string comparison to identify an SOF
+parent device/driver.
+
+Suggested-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@linux.intel.com>
+Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
+Link: https://lore.kernel.org/r/20201112223825.39765-5-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ include/sound/soc-acpi.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
+index b16a844d1..9a43c44dc 100644
+--- a/include/sound/soc-acpi.h
++++ b/include/sound/soc-acpi.h
+@@ -171,4 +171,10 @@ struct snd_soc_acpi_codecs {
+ u8 codecs[SND_SOC_ACPI_MAX_CODECS][ACPI_ID_LEN];
+ };
+
++static inline bool snd_soc_acpi_sof_parent(struct device *dev)
++{
++ return dev->parent && dev->parent->driver && dev->parent->driver->name &&
++ !strcmp(dev->parent->driver->name, "sof-audio-acpi");
++}
++
+ #endif
+--
+2.29.2
+
diff --git a/Patchlist b/Patchlist
index 29f117c52..d5403dbc0 100644
--- a/Patchlist
+++ b/Patchlist
@@ -96,3 +96,4 @@
0001-drm-panel-st7703-Assert-reset-prior-to-powering-down.patch
0001-arm64-dts-sun50i-a64-pinephone-Enable-LCD-support-on.patch
0001-arm64-dts-sun50i-a64-pinephone-Add-touchscreen-suppo.patch
+0001-WM5102.patch
diff --git a/filter-x86_64.sh b/filter-x86_64.sh
index 1aa80f2e0..08b65440b 100644
--- a/filter-x86_64.sh
+++ b/filter-x86_64.sh
@@ -9,4 +9,6 @@
# modifications to the overrides below. If something should be removed across
# all arches, remove it in the default instead of per-arch.
-# Defaults work so no need to override
+driverdirs="$driverdirs extcon regulator"
+
+inputdrvs="$inputdrvs misc"
diff --git a/filter-x86_64.sh.fedora b/filter-x86_64.sh.fedora
index 1aa80f2e0..08b65440b 100644
--- a/filter-x86_64.sh.fedora
+++ b/filter-x86_64.sh.fedora
@@ -9,4 +9,6 @@
# modifications to the overrides below. If something should be removed across
# all arches, remove it in the default instead of per-arch.
-# Defaults work so no need to override
+driverdirs="$driverdirs extcon regulator"
+
+inputdrvs="$inputdrvs misc"
diff --git a/kernel-local b/kernel-local
index 8c32be5be..dfe520aac 100644
--- a/kernel-local
+++ b/kernel-local
@@ -1,2 +1,20 @@
# This file is intentionally left empty in the stock kernel. Its a nicety
# added for those wanting to do custom rebuilds with altered config opts.
+CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH=m
+
+CONFIG_MFD_ARIZONA=y
+CONFIG_MFD_ARIZONA_I2C=m
+CONFIG_MFD_ARIZONA_SPI=m
+
+CONFIG_REGULATOR_ARIZONA_LDO1=m
+
+CONFIG_GPIO_ARIZONA=m
+CONFIG_MFD_CS47L24=y
+CONFIG_MFD_WM5102=y
+CONFIG_MFD_WM5110=y
+CONFIG_MFD_WM8997=y
+CONFIG_MFD_WM8998=y
+
+CONFIG_EXTCON_ARIZONA=m
+CONFIG_REGULATOR_ARIZONA_MICSUPP=m
+CONFIG_INPUT_ARIZONA_HAPTICS=m
diff --git a/kernel.spec b/kernel.spec
index c4a7c26b7..7504e0726 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -58,7 +58,7 @@ Summary: The Linux kernel
%global zcpu `nproc --all`
%endif
-# define buildid .local
+%define buildid wm5102_1
%if 0%{?fedora}
%define primary_target fedora
@@ -852,6 +852,9 @@ Patch104: 0001-brcm-rpi4-fix-usb-numeration.patch
# RPi-4 and wifi issues
Patch105: arm-dts-rpi-4-disable-wifi-frequencies.patch
+# Add wm5102 support
+Patch200: 0001-WM5102.patch
+
# END OF PATCH DEFINITIONS
%endif
--
2.29.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment