From ec5df91beef8571b504407b62ce9670d9f84e639 Mon Sep 17 00:00:00 2001 From: "Alexander \"PapaTutuWawa" Date: Fri, 30 Jul 2021 11:25:02 +0200 Subject: [PATCH] test --- ayame.nix | 29 + ...a-Add-jack-pointer-to-struct-arizona.patch | 52 ++ ...-Add-MODULE_SOFTDEP-pre-arizona_ldo1.patch | 62 ++ ...support-for-ACPI-enumeration-of-WM51.patch | 192 ++++++ ...w-building-arizona-MFD-core-as-modul.patch | 87 +++ ...ix-some-issues-when-HPDET-IRQ-fires-.patch | 86 +++ ...a-Fix-various-races-on-driver-unbind.patch | 122 ++++ .../0007-extcon-arizona-Fix-modalias.patch | 29 + ...ix-flags-parameter-to-the-gpiod_get-.patch | 32 + ...-Add-arizona_set_extcon_state-helper.patch | 119 ++++ ...lso-report-jack-state-through-snd_so.patch | 62 ++ ...se-ASoC-jack-input-device-when-avail.patch | 110 ++++ ...MI-quirk-table-to-soc_intel_is_byt_c.patch | 74 +++ ..._wm5102-Add-machine-driver-for-BYT-W.patch | 599 ++++++++++++++++++ ...bytcr_wm5102-Add-jack-detect-support.patch | 123 ++++ 15 files changed, 1778 insertions(+) create mode 100644 patches/ayame/0001-mfd-arizona-Add-jack-pointer-to-struct-arizona.patch create mode 100644 patches/ayame/0002-mfd-arizona-Add-MODULE_SOFTDEP-pre-arizona_ldo1.patch create mode 100644 patches/ayame/0003-mfd-arizona-Add-support-for-ACPI-enumeration-of-WM51.patch create mode 100644 patches/ayame/0004-mfd-arizona-Allow-building-arizona-MFD-core-as-modul.patch create mode 100644 patches/ayame/0005-extcon-arizona-Fix-some-issues-when-HPDET-IRQ-fires-.patch create mode 100644 patches/ayame/0006-extcon-arizona-Fix-various-races-on-driver-unbind.patch create mode 100644 patches/ayame/0007-extcon-arizona-Fix-modalias.patch create mode 100644 patches/ayame/0008-extcon-arizona-Fix-flags-parameter-to-the-gpiod_get-.patch create mode 100644 patches/ayame/0009-extcon-arizona-Add-arizona_set_extcon_state-helper.patch create mode 100644 patches/ayame/0010-extcon-arizona-Also-report-jack-state-through-snd_so.patch create mode 100644 patches/ayame/0011-extcon-arizona-Use-ASoC-jack-input-device-when-avail.patch create mode 100644 patches/ayame/0012-ASoC-Intel-Add-DMI-quirk-table-to-soc_intel_is_byt_c.patch create mode 100644 patches/ayame/0013-ASoC-Intel-bytcr_wm5102-Add-machine-driver-for-BYT-W.patch create mode 100644 patches/ayame/0014-ASoC-Intel-bytcr_wm5102-Add-jack-detect-support.patch diff --git a/ayame.nix b/ayame.nix index 8b6f40c..f9e46b9 100644 --- a/ayame.nix +++ b/ayame.nix @@ -3,6 +3,10 @@ let customPkgs = import ./packages/overlay.nix; unstable = (import ./modules/unstable.nix config); + mkPatch = name: { + name = name; + patch = ./patches/ayame/"${name}"; + }; in { imports = [ ./generic.nix @@ -57,6 +61,31 @@ in { kernelParams = [ "modprobe.blacklist=arizona_spi" ]; kernelModules = []; extraModulePackages = []; + kernelPatches = [ + (mkPatch 0001-mfd-arizona-Add-jack-pointer-to-struct-arizona.patch) + (mkPatch 0002-mfd-arizona-Add-MODULE_SOFTDEP-pre-arizona_ldo1.patch) + (mkPatch 0003-mfd-arizona-Add-support-for-ACPI-enumeration-of-WM51.patch) + (mkPatch 0004-mfd-arizona-Allow-building-arizona-MFD-core-as-modul.patch) + (mkPatch 0005-extcon-arizona-Fix-some-issues-when-HPDET-IRQ-fires-.patch) + (mkPatch 0006-extcon-arizona-Fix-various-races-on-driver-unbind.patch) + (mkPatch 0007-extcon-arizona-Fix-modalias.patch) + (mkPatch 0008-extcon-arizona-Fix-flags-parameter-to-the-gpiod_get-.patch) + (mkPatch 0009-extcon-arizona-Add-arizona_set_extcon_state-helper.patch) + (mkPatch 0010-extcon-arizona-Also-report-jack-state-through-snd_so.patch) + (mkPatch 0011-extcon-arizona-Use-ASoC-jack-input-device-when-avail.patch) + (mkPatch 0012-ASoC-Intel-Add-DMI-quirk-table-to-soc_intel_is_byt_c.patch) + (mkPatch 0013-ASoC-Intel-bytcr_wm5102-Add-machine-driver-for-BYT-W.patch) + (mkPatch 0014-ASoC-Intel-bytcr_wm5102-Add-jack-detect-support.patch) + { + name = "enable-wm5102"; + patch = null; + extraConfig = '' + EXTCON_ARIZONA=m + MFD_WM5102=y + SND_SOC_WM5102=m + ''; + } + ]; kernelPackages = pkgs.linuxPackages_zen; }; diff --git a/patches/ayame/0001-mfd-arizona-Add-jack-pointer-to-struct-arizona.patch b/patches/ayame/0001-mfd-arizona-Add-jack-pointer-to-struct-arizona.patch new file mode 100644 index 0000000..fc8b1b4 --- /dev/null +++ b/patches/ayame/0001-mfd-arizona-Add-jack-pointer-to-struct-arizona.patch @@ -0,0 +1,52 @@ +From 050388b1503e895deeff7f95bbdc3efb3d712aa2 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 23 Dec 2020 12:55:10 +0100 +Subject: [PATCH 01/14] mfd: arizona: Add jack pointer to struct arizona + +The Linux Arizona driver uses the MFD framework to create several +sub-devices for the Arizona codec and then uses a driver per function. + +The jack-detect support for the Arizona codec is handled by the +extcon-arizona driver. This driver exports info about the jack state +to userspace through the standard extcon sysfs class interface. + +But standard Linux userspace does not monitor/use the extcon sysfs +interface for jack-detection. + +Add a jack pointer to the shared arizona data struct, this allows +the ASoC machine driver to create a snd_soc_jack and then pass this +to the extcon-arizona driver to report jack-detect state, so that +jack-detection works with standard Linux userspace. + +The extcon-arizona code already depends on (waits for with -EPROBE_DEFER) +the snd_card being registered by the machine driver, so this does not +cause any ordering issues. + +Signed-off-by: Hans de Goede +--- + include/linux/mfd/arizona/core.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h +index 6d6f96b2b29f..5eb269bdbfcb 100644 +--- a/include/linux/mfd/arizona/core.h ++++ b/include/linux/mfd/arizona/core.h +@@ -115,6 +115,7 @@ enum arizona_type { + #define ARIZONA_NUM_IRQ 75 + + struct snd_soc_dapm_context; ++struct snd_soc_jack; + + struct arizona { + struct regmap *regmap; +@@ -148,6 +149,7 @@ struct arizona { + bool ctrlif_error; + + struct snd_soc_dapm_context *dapm; ++ struct snd_soc_jack *jack; + + int tdm_width[ARIZONA_MAX_AIF]; + int tdm_slots[ARIZONA_MAX_AIF]; +-- +2.28.0 + diff --git a/patches/ayame/0002-mfd-arizona-Add-MODULE_SOFTDEP-pre-arizona_ldo1.patch b/patches/ayame/0002-mfd-arizona-Add-MODULE_SOFTDEP-pre-arizona_ldo1.patch new file mode 100644 index 0000000..d39035a --- /dev/null +++ b/patches/ayame/0002-mfd-arizona-Add-MODULE_SOFTDEP-pre-arizona_ldo1.patch @@ -0,0 +1,62 @@ +From 9c530723d4a82322c072079e78d2ce856d6dcdc1 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 7 Dec 2020 10:12:27 +0100 +Subject: [PATCH 02/14] 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 doftdep 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. + +Signed-off-by: Hans de Goede +--- + 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 4b58e3ad6eb6..2a4a3a164d0a 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 "); + MODULE_LICENSE("GPL"); +diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c +index 2633e147b76c..704f214d2614 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 "); + MODULE_LICENSE("GPL"); +-- +2.28.0 + diff --git a/patches/ayame/0003-mfd-arizona-Add-support-for-ACPI-enumeration-of-WM51.patch b/patches/ayame/0003-mfd-arizona-Add-support-for-ACPI-enumeration-of-WM51.patch new file mode 100644 index 0000000..949a892 --- /dev/null +++ b/patches/ayame/0003-mfd-arizona-Add-support-for-ACPI-enumeration-of-WM51.patch @@ -0,0 +1,192 @@ +From 73c418d5f8f0edbdeae3a47a0c916961decf5fdc Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 6 Dec 2020 17:50:17 +0100 +Subject: [PATCH 03/14] 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 +Signed-off-by: Hans de Goede +--- + drivers/mfd/arizona-spi.c | 120 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 120 insertions(+) + +diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c +index 704f214d2614..bcdbd72fefb5 100644 +--- a/drivers/mfd/arizona-spi.c ++++ b/drivers/mfd/arizona-spi.c +@@ -7,7 +7,10 @@ + * Author: Mark Brown + */ + ++#include + #include ++#include ++#include + #include + #include + #include +@@ -15,11 +18,119 @@ + #include + #include + #include ++#include + + #include + + #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; ++ int i, 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); ++ for (i = 0; i < ARRAY_SIZE(arizona_soc_gpios); i++) ++ lookup->table[i] = arizona_soc_gpios[i]; ++ ++ 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 */ ++ acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL); ++ ++ /* ++ * 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. ++ */ ++ 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 void arizona_spi_acpi_probe(struct arizona *arizona) ++{ ++} ++#endif ++ + static int arizona_spi_probe(struct spi_device *spi) + { + const struct spi_device_id *id = spi_get_device_id(spi); +@@ -30,6 +141,8 @@ static int arizona_spi_probe(struct spi_device *spi) + + if (spi->dev.of_node) + type = arizona_of_get_type(&spi->dev); ++ else if (ACPI_COMPANION(&spi->dev)) ++ type = (unsigned long)acpi_device_get_match_data(&spi->dev); + else + type = id->driver_data; + +@@ -75,6 +188,12 @@ static int arizona_spi_probe(struct spi_device *spi) + arizona->dev = &spi->dev; + arizona->irq = spi->irq; + ++ if (ACPI_COMPANION(&spi->dev)) { ++ ret = arizona_spi_acpi_probe(arizona); ++ if (ret) ++ return ret; ++ } ++ + return arizona_dev_init(arizona); + } + +@@ -102,6 +221,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.28.0 + diff --git a/patches/ayame/0004-mfd-arizona-Allow-building-arizona-MFD-core-as-modul.patch b/patches/ayame/0004-mfd-arizona-Allow-building-arizona-MFD-core-as-modul.patch new file mode 100644 index 0000000..d2b5f1f --- /dev/null +++ b/patches/ayame/0004-mfd-arizona-Allow-building-arizona-MFD-core-as-modul.patch @@ -0,0 +1,87 @@ +From f9112e46b682e21fa26488ce4d5794edaf850837 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 25 Dec 2020 12:49:33 +0100 +Subject: [PATCH 04/14] mfd: arizona: Allow building arizona MFD-core as module + +There is no reason why the arizona core,irq and codec model specific +regmap bits cannot be build as a module. All they do is export symbols +which are used by the arizona-spi and/or arizona-i2c modules, which +themselves can be built as module. + +Change the Kconfig and Makefile arizona bits so that the arizona MFD-core +can be built as a module. + +This is especially useful on x86 platforms with a WM5102 codec, this +allows the arizona MFD driver necessary for the WM5102 codec to be +enabled in generic distro-kernels without growing the base kernel-image +size. + +Signed-off-by: Hans de Goede +--- + drivers/mfd/Kconfig | 2 +- + drivers/mfd/Makefile | 14 +++++++------- + drivers/mfd/arizona-core.c | 2 ++ + 3 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index cc0b73280c68..8fe9e10eaf51 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -1831,7 +1831,7 @@ config MFD_ARIZONA + select REGMAP + select REGMAP_IRQ + select MFD_CORE +- bool ++ tristate + + config MFD_ARIZONA_I2C + tristate "Cirrus Logic/Wolfson Microelectronics Arizona platform with I2C" +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 14fdb188af02..3f208af1664f 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -41,24 +41,24 @@ obj-$(CONFIG_MFD_TQMX86) += tqmx86.o + + obj-$(CONFIG_MFD_LOCHNAGAR) += lochnagar-i2c.o + +-obj-$(CONFIG_MFD_ARIZONA) += arizona-core.o +-obj-$(CONFIG_MFD_ARIZONA) += arizona-irq.o ++arizona-objs := arizona-core.o arizona-irq.o ++obj-$(CONFIG_MFD_ARIZONA) += arizona.o + obj-$(CONFIG_MFD_ARIZONA_I2C) += arizona-i2c.o + obj-$(CONFIG_MFD_ARIZONA_SPI) += arizona-spi.o + ifeq ($(CONFIG_MFD_WM5102),y) +-obj-$(CONFIG_MFD_ARIZONA) += wm5102-tables.o ++arizona-objs += wm5102-tables.o + endif + ifeq ($(CONFIG_MFD_WM5110),y) +-obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o ++arizona-objs += wm5110-tables.o + endif + ifeq ($(CONFIG_MFD_WM8997),y) +-obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o ++arizona-objs += wm8997-tables.o + endif + ifeq ($(CONFIG_MFD_WM8998),y) +-obj-$(CONFIG_MFD_ARIZONA) += wm8998-tables.o ++arizona-objs += wm8998-tables.o + endif + ifeq ($(CONFIG_MFD_CS47L24),y) +-obj-$(CONFIG_MFD_ARIZONA) += cs47l24-tables.o ++arizona-objs += cs47l24-tables.o + endif + obj-$(CONFIG_MFD_WCD934X) += wcd934x.o + obj-$(CONFIG_MFD_WM8400) += wm8400-core.o +diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c +index 000cb82023e3..a9ba1c865abf 100644 +--- a/drivers/mfd/arizona-core.c ++++ b/drivers/mfd/arizona-core.c +@@ -1478,3 +1478,5 @@ int arizona_dev_exit(struct arizona *arizona) + return 0; + } + EXPORT_SYMBOL_GPL(arizona_dev_exit); ++ ++MODULE_LICENSE("GPL v2"); +-- +2.28.0 + diff --git a/patches/ayame/0005-extcon-arizona-Fix-some-issues-when-HPDET-IRQ-fires-.patch b/patches/ayame/0005-extcon-arizona-Fix-some-issues-when-HPDET-IRQ-fires-.patch new file mode 100644 index 0000000..41ab56c --- /dev/null +++ b/patches/ayame/0005-extcon-arizona-Fix-some-issues-when-HPDET-IRQ-fires-.patch @@ -0,0 +1,86 @@ +From c85886b2901593aef688b0c7a6a3b66222e99a90 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 22 Dec 2020 17:34:06 +0100 +Subject: [PATCH 05/14] extcon: arizona: Fix some issues when HPDET IRQ fires + after the jack has been unplugged + +When the jack is partially inserted and then removed again it may be +removed while the hpdet code is running. In this case the following +may happen: + +1. The "JACKDET rise" or ""JACKDET fall" IRQ triggers +2. arizona_jackdet runs and takes info->lock +3. The "HPDET" IRQ triggers +4. arizona_hpdet_irq runs, blocks on info->lock +5. arizona_jackdet calls arizona_stop_mic() and clears info->hpdet_done +6. arizona_jackdet releases info->lock +7. arizona_hpdet_irq now can continue running and: +7.1 Calls arizona_start_mic() (if a mic was detected) +7.2 sets info->hpdet_done + +Step 7 is undeseriable / a bug: +7.1 causes the device to stay in a high power-state (with MICVDD enabled) +7.2 causes hpdet to not run on the next jack insertion, which in turn + causes the EXTCON_JACK_HEADPHONE state to never get set + +This fixes both issues by skipping these 2 steps when arizona_hpdet_irq +runs after the jack has been unplugged. + +Signed-off-by: Hans de Goede +--- + drivers/extcon/extcon-arizona.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c +index aae82db542a5..f7ef247de46a 100644 +--- a/drivers/extcon/extcon-arizona.c ++++ b/drivers/extcon/extcon-arizona.c +@@ -601,7 +601,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) + struct arizona *arizona = info->arizona; + int id_gpio = arizona->pdata.hpdet_id_gpio; + unsigned int report = EXTCON_JACK_HEADPHONE; +- int ret, reading; ++ int ret, reading, state; + bool mic = false; + + mutex_lock(&info->lock); +@@ -614,12 +614,11 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) + } + + /* If the cable was removed while measuring ignore the result */ +- ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); +- if (ret < 0) { +- dev_err(arizona->dev, "Failed to check cable state: %d\n", +- ret); ++ state = extcon_get_state(info->edev, EXTCON_MECHANICAL); ++ if (state < 0) { ++ dev_err(arizona->dev, "Failed to check cable state: %d\n", state); + goto out; +- } else if (!ret) { ++ } else if (!state) { + dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n"); + goto done; + } +@@ -667,7 +666,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) + gpio_set_value_cansleep(id_gpio, 0); + + /* If we have a mic then reenable MICDET */ +- if (mic || info->mic) ++ if (state && (mic || info->mic)) + arizona_start_mic(info); + + if (info->hpdet_active) { +@@ -675,7 +674,9 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) + info->hpdet_active = false; + } + +- info->hpdet_done = true; ++ /* Do not set hp_det done when the cable has been unplugged */ ++ if (state) ++ info->hpdet_done = true; + + out: + mutex_unlock(&info->lock); +-- +2.28.0 + diff --git a/patches/ayame/0006-extcon-arizona-Fix-various-races-on-driver-unbind.patch b/patches/ayame/0006-extcon-arizona-Fix-various-races-on-driver-unbind.patch new file mode 100644 index 0000000..6b2e32c --- /dev/null +++ b/patches/ayame/0006-extcon-arizona-Fix-various-races-on-driver-unbind.patch @@ -0,0 +1,122 @@ +From 2bc945b3018a3e5bac56e762c721447e804d6119 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 22 Dec 2020 17:48:53 +0100 +Subject: [PATCH 06/14] extcon: arizona: Fix various races on driver unbind + +We must free/disable all interrupts and cancel all pending works +before doing further cleanup. + +Before this commit arizona_extcon_remove() was doing several +register writes to shut things down before disabling the IRQs +and it was cancelling only 1 of the 3 different works used. + +Move all the register-writes shutting things down to after +the disabling of the IRQs and add the 2 missing +cancel_delayed_work_sync() calls. + +This fixes various possible races on driver unbind. One of which +would always trigger on devices using the mic-clamp feature for +jack detection. The ARIZONA_MICD_CLAMP_MODE_MASK update was +done before disabling the IRQs, causing: +1. arizona_jackdet() to run +2. detect a jack being inserted (clamp disabled means jack inserted) +3. call arizona_start_mic() which: +3.1 Enables the MICVDD regulator +3.2 takes a pm_runtime_reference + +And this was all happening after the ARIZONA_MICD_ENA bit clearing, +which would undo 3.1 and 3.2 because the ARIZONA_MICD_CLAMP_MODE_MASK +update was being done after the ARIZONA_MICD_ENA bit clearing. + +So this means that arizona_extcon_remove() would exit with +1. MICVDD enabled and 2. The pm_runtime_reference being unbalanced. + +MICVDD still being enabled caused the following oops when the +regulator is released by the devm framework: + +[ 2850.745757] ------------[ cut here ]------------ +[ 2850.745827] WARNING: CPU: 2 PID: 2098 at drivers/regulator/core.c:2123 _regulator_put.part.0+0x19f/0x1b0 +[ 2850.745835] Modules linked in: extcon_arizona ... +... +[ 2850.746909] Call Trace: +[ 2850.746932] regulator_put+0x2d/0x40 +[ 2850.746946] release_nodes+0x22a/0x260 +[ 2850.746984] __device_release_driver+0x190/0x240 +[ 2850.747002] driver_detach+0xd4/0x120 +... +[ 2850.747337] ---[ end trace f455dfd7abd9781f ]--- + +Note this oops is just one of various theoretically possible races caused +by the wrong ordering inside arizona_extcon_remove(), this fixes the +ordering fixing all possible races, including the reported oops. + +Signed-off-by: Hans de Goede +--- + drivers/extcon/extcon-arizona.c | 40 +++++++++++++++++---------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c +index f7ef247de46a..76aacbac5869 100644 +--- a/drivers/extcon/extcon-arizona.c ++++ b/drivers/extcon/extcon-arizona.c +@@ -1760,25 +1760,6 @@ static int arizona_extcon_remove(struct platform_device *pdev) + bool change; + int ret; + +- ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, +- ARIZONA_MICD_ENA, 0, +- &change); +- if (ret < 0) { +- dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", +- ret); +- } else if (change) { +- regulator_disable(info->micvdd); +- pm_runtime_put(info->dev); +- } +- +- gpiod_put(info->micd_pol_gpio); +- +- pm_runtime_disable(&pdev->dev); +- +- regmap_update_bits(arizona->regmap, +- ARIZONA_MICD_CLAMP_CONTROL, +- ARIZONA_MICD_CLAMP_MODE_MASK, 0); +- + if (info->micd_clamp) { + jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; + jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; +@@ -1794,10 +1775,31 @@ static int arizona_extcon_remove(struct platform_device *pdev) + arizona_free_irq(arizona, jack_irq_rise, info); + arizona_free_irq(arizona, jack_irq_fall, info); + cancel_delayed_work_sync(&info->hpdet_work); ++ cancel_delayed_work_sync(&info->micd_detect_work); ++ cancel_delayed_work_sync(&info->micd_timeout_work); ++ ++ ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, ++ ARIZONA_MICD_ENA, 0, ++ &change); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", ++ ret); ++ } else if (change) { ++ regulator_disable(info->micvdd); ++ pm_runtime_put(info->dev); ++ } ++ ++ regmap_update_bits(arizona->regmap, ++ ARIZONA_MICD_CLAMP_CONTROL, ++ ARIZONA_MICD_CLAMP_MODE_MASK, 0); + regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, + ARIZONA_JD1_ENA, 0); + arizona_clk32k_disable(arizona); + ++ gpiod_put(info->micd_pol_gpio); ++ ++ pm_runtime_disable(&pdev->dev); ++ + return 0; + } + +-- +2.28.0 + diff --git a/patches/ayame/0007-extcon-arizona-Fix-modalias.patch b/patches/ayame/0007-extcon-arizona-Fix-modalias.patch new file mode 100644 index 0000000..f80a7f8 --- /dev/null +++ b/patches/ayame/0007-extcon-arizona-Fix-modalias.patch @@ -0,0 +1,29 @@ +From 399f229249269addcb5aba4c54d920d7c66955ed Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 22 Dec 2020 18:05:51 +0100 +Subject: [PATCH 07/14] extcon: arizona: Fix modalias + +Fix the modalias so that the driver will be loaded automatically. The +module's name is "extcon-arizona", following other extcon module-names. + +But the driver's and platform-device's name is "arizona-extcon" and the +modalias must match that. + +Signed-off-by: Hans de Goede +--- + drivers/extcon/extcon-arizona.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c +index 76aacbac5869..95acfe7620fd 100644 +--- a/drivers/extcon/extcon-arizona.c ++++ b/drivers/extcon/extcon-arizona.c +@@ -1816,4 +1816,4 @@ module_platform_driver(arizona_extcon_driver); + MODULE_DESCRIPTION("Arizona Extcon driver"); + MODULE_AUTHOR("Mark Brown "); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("platform:extcon-arizona"); ++MODULE_ALIAS("platform:arizona-extcon"); +-- +2.28.0 + diff --git a/patches/ayame/0008-extcon-arizona-Fix-flags-parameter-to-the-gpiod_get-.patch b/patches/ayame/0008-extcon-arizona-Fix-flags-parameter-to-the-gpiod_get-.patch new file mode 100644 index 0000000..595bbb8 --- /dev/null +++ b/patches/ayame/0008-extcon-arizona-Fix-flags-parameter-to-the-gpiod_get-.patch @@ -0,0 +1,32 @@ +From 72d8e5732bc962b46dfbdc767ae6f7c5804e95c3 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 22 Dec 2020 18:08:43 +0100 +Subject: [PATCH 08/14] extcon: arizona: Fix flags parameter to the + gpiod_get("wlf,micd-pol") call + +The initial value of the GPIO should match the info->micd_modes[0].gpio +value. arizona_extcon_probe() already stores the necessary flag in a +mode variable, but instead of passing mode as flags to the gpiod_get() +it was using a hardcoded GPIOD_OUT_LOW. + +Signed-off-by: Hans de Goede +--- + drivers/extcon/extcon-arizona.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c +index 95acfe7620fd..145ca5cd40d5 100644 +--- a/drivers/extcon/extcon-arizona.c ++++ b/drivers/extcon/extcon-arizona.c +@@ -1510,7 +1510,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) + */ + info->micd_pol_gpio = gpiod_get_optional(arizona->dev, + "wlf,micd-pol", +- GPIOD_OUT_LOW); ++ mode); + if (IS_ERR(info->micd_pol_gpio)) { + ret = PTR_ERR(info->micd_pol_gpio); + dev_err(arizona->dev, +-- +2.28.0 + diff --git a/patches/ayame/0009-extcon-arizona-Add-arizona_set_extcon_state-helper.patch b/patches/ayame/0009-extcon-arizona-Add-arizona_set_extcon_state-helper.patch new file mode 100644 index 0000000..3ee5a18 --- /dev/null +++ b/patches/ayame/0009-extcon-arizona-Add-arizona_set_extcon_state-helper.patch @@ -0,0 +1,119 @@ +From bf992404b91f0283feb436dfb60e692763608cda Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 22 Dec 2020 20:27:56 +0100 +Subject: [PATCH 09/14] extcon: arizona: Add arizona_set_extcon_state() helper + +All the callers of extcon_set_state_sync() log an error on failure, +without doing any further error-handling (as there is nothing they +can do about the error). + +Factor this out into a helper to remove some duplicate code. + +Signed-off-by: Hans de Goede +--- + drivers/extcon/extcon-arizona.c | 47 ++++++++++++--------------------- + 1 file changed, 17 insertions(+), 30 deletions(-) + +diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c +index 145ca5cd40d5..d5b3231744f9 100644 +--- a/drivers/extcon/extcon-arizona.c ++++ b/drivers/extcon/extcon-arizona.c +@@ -595,6 +595,16 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading, + return 0; + } + ++static void arizona_set_extcon_state(struct arizona_extcon_info *info, ++ unsigned int id, bool state) ++{ ++ int ret; ++ ++ ret = extcon_set_state_sync(info->edev, id, state); ++ if (ret) ++ dev_err(info->arizona->dev, "Failed to set extcon state: %d\n", ret); ++} ++ + static irqreturn_t arizona_hpdet_irq(int irq, void *data) + { + struct arizona_extcon_info *info = data; +@@ -648,11 +658,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) + else + report = EXTCON_JACK_HEADPHONE; + +- ret = extcon_set_state_sync(info->edev, report, true); +- if (ret != 0) +- dev_err(arizona->dev, "Failed to report HP/line: %d\n", +- ret); +- ++ arizona_set_extcon_state(info, report, true); + done: + /* Reset back to starting range */ + regmap_update_bits(arizona->regmap, +@@ -727,9 +733,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info) + pm_runtime_put_autosuspend(info->dev); + + /* Just report headphone */ +- ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); +- if (ret != 0) +- dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); ++ arizona_set_extcon_state(info, EXTCON_JACK_HEADPHONE, true); + + if (info->mic) + arizona_start_mic(info); +@@ -781,10 +785,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) + + err: + /* Just report headphone */ +- ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); +- if (ret != 0) +- dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); +- ++ arizona_set_extcon_state(info, EXTCON_JACK_HEADPHONE, true); + info->hpdet_active = false; + } + +@@ -904,11 +905,7 @@ static int arizona_micdet_reading(void *priv) + + arizona_identify_headphone(info); + +- ret = extcon_set_state_sync(info->edev, +- EXTCON_JACK_MICROPHONE, true); +- if (ret != 0) +- dev_err(arizona->dev, "Headset report failed: %d\n", +- ret); ++ arizona_set_extcon_state(info, EXTCON_JACK_MICROPHONE, true); + + /* Don't need to regulate for button detection */ + ret = regulator_allow_bypass(info->micvdd, true); +@@ -1175,12 +1172,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) + + if (info->last_jackdet == present) { + dev_dbg(arizona->dev, "Detected jack\n"); +- ret = extcon_set_state_sync(info->edev, +- EXTCON_MECHANICAL, true); +- +- if (ret != 0) +- dev_err(arizona->dev, "Mechanical report failed: %d\n", +- ret); ++ arizona_set_extcon_state(info, EXTCON_MECHANICAL, true); + + info->detecting = true; + info->mic = false; +@@ -1216,13 +1208,8 @@ static irqreturn_t arizona_jackdet(int irq, void *data) + info->micd_ranges[i].key, 0); + input_sync(info->input); + +- for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) { +- ret = extcon_set_state_sync(info->edev, +- arizona_cable[i], false); +- if (ret != 0) +- dev_err(arizona->dev, +- "Removal report failed: %d\n", ret); +- } ++ for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) ++ arizona_set_extcon_state(info, arizona_cable[i], false); + + /* + * If the jack was removed during a headphone detection we +-- +2.28.0 + diff --git a/patches/ayame/0010-extcon-arizona-Also-report-jack-state-through-snd_so.patch b/patches/ayame/0010-extcon-arizona-Also-report-jack-state-through-snd_so.patch new file mode 100644 index 0000000..49a7715 --- /dev/null +++ b/patches/ayame/0010-extcon-arizona-Also-report-jack-state-through-snd_so.patch @@ -0,0 +1,62 @@ +From e827a5cac13500bab604e1a3d410fb8910dad62c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 24 Dec 2020 14:52:16 +0100 +Subject: [PATCH 10/14] extcon: arizona: Also report jack state through + snd_soc_jack_report() + +The Linux Arizona driver uses the MFD framework to create several +sub-devices for the Arizona codec and then uses a driver per function. + +The extcon-arizona driver handles jack-detect support and exports info +about the jack state to userspace through the standard extcon sysfs +class interface. + +Standard Linux userspace does not monitor/use the extcon sysfs interface +for jack-detection, resulting in the jack-state not being taken into +account by userspace. + +The ASoC machine-driver may have created a standard ASoC jack when +registering the card. In this case also report the jack-state through the +ASoC jack so that jack-detection works with standard Linux userspace. + +Signed-off-by: Hans de Goede +--- + drivers/extcon/extcon-arizona.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c +index d5b3231744f9..931a7d239aea 100644 +--- a/drivers/extcon/extcon-arizona.c ++++ b/drivers/extcon/extcon-arizona.c +@@ -20,6 +20,7 @@ + #include + #include + ++#include + #include + + #include +@@ -598,11 +599,19 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading, + static void arizona_set_extcon_state(struct arizona_extcon_info *info, + unsigned int id, bool state) + { +- int ret; ++ int ret, mask = 0; + + ret = extcon_set_state_sync(info->edev, id, state); + if (ret) + dev_err(info->arizona->dev, "Failed to set extcon state: %d\n", ret); ++ ++ switch (id) { ++ case EXTCON_JACK_HEADPHONE: mask = SND_JACK_HEADPHONE; break; ++ case EXTCON_JACK_MICROPHONE: mask = SND_JACK_MICROPHONE; break; ++ } ++ ++ if (info->arizona->jack && mask) ++ snd_soc_jack_report(info->arizona->jack, state ? mask : 0, mask); + } + + static irqreturn_t arizona_hpdet_irq(int irq, void *data) +-- +2.28.0 + diff --git a/patches/ayame/0011-extcon-arizona-Use-ASoC-jack-input-device-when-avail.patch b/patches/ayame/0011-extcon-arizona-Use-ASoC-jack-input-device-when-avail.patch new file mode 100644 index 0000000..f784d5d --- /dev/null +++ b/patches/ayame/0011-extcon-arizona-Use-ASoC-jack-input-device-when-avail.patch @@ -0,0 +1,110 @@ +From 72dbb22e561863e77fe07a12d03ed815d5e6a371 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 24 Dec 2020 19:54:03 +0100 +Subject: [PATCH 11/14] extcon: arizona: Use ASoC jack input-device when + available + +When the machine driver creates an ASoC jack for jack-detect and +CONFIG_SND_JACK_INPUT_DEV is enabled then this will also create an +input-device. In this case use the already created input-device +to report button presses instead of creating a second "Headset" +input-device for the same headset. + +This relies on the machine-driver setting up the jack-input-device to +report the EV_KEY key-codes configured in arizona_pdata.micd_ranges, +before registering it. + +Signed-off-by: Hans de Goede +--- + drivers/extcon/extcon-arizona.c | 46 +++++++++++++++++++++++---------- + 1 file changed, 32 insertions(+), 14 deletions(-) + +diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c +index 931a7d239aea..292ca4088418 100644 +--- a/drivers/extcon/extcon-arizona.c ++++ b/drivers/extcon/extcon-arizona.c +@@ -1376,6 +1376,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) + { + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct arizona_pdata *pdata = &arizona->pdata; ++ bool using_jack_input_dev = false; + struct arizona_extcon_info *info; + unsigned int val; + unsigned int clamp_mode; +@@ -1453,15 +1454,28 @@ static int arizona_extcon_probe(struct platform_device *pdev) + return ret; + } + +- info->input = devm_input_allocate_device(&pdev->dev); +- if (!info->input) { +- dev_err(arizona->dev, "Can't allocate input dev\n"); +- ret = -ENOMEM; +- return ret; +- } ++#ifdef CONFIG_SND_JACK_INPUT_DEV ++ if (arizona->jack) { ++ info->input = input_get_device(arizona->jack->jack->input_dev); ++ using_jack_input_dev = true; ++ } else ++#endif ++ { ++ info->input = devm_input_allocate_device(&pdev->dev); ++ if (!info->input) { ++ dev_err(arizona->dev, "Can't allocate input dev\n"); ++ ret = -ENOMEM; ++ return ret; ++ } + +- info->input->name = "Headset"; +- info->input->phys = "arizona/extcon"; ++ /* ++ * balance the put in arizona_extcon_remove, which is necessary ++ * when re-using the jack-device's input-device. ++ */ ++ input_get_device(info->input); ++ info->input->name = "Headset"; ++ info->input->phys = "arizona/extcon"; ++ } + + if (!pdata->micd_timeout) + pdata->micd_timeout = DEFAULT_MICD_TIMEOUT; +@@ -1603,8 +1617,9 @@ static int arizona_extcon_probe(struct platform_device *pdev) + arizona_micd_levels[j], i); + + arizona_micd_set_level(arizona, i, j); +- input_set_capability(info->input, EV_KEY, +- info->micd_ranges[i].key); ++ if (!using_jack_input_dev) ++ input_set_capability(info->input, EV_KEY, ++ info->micd_ranges[i].key); + + /* Enable reporting of that range */ + regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2, +@@ -1718,10 +1733,12 @@ static int arizona_extcon_probe(struct platform_device *pdev) + dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", + ret); + +- ret = input_register_device(info->input); +- if (ret) { +- dev_err(&pdev->dev, "Can't register input device: %d\n", ret); +- goto err_hpdet; ++ if (!using_jack_input_dev) { ++ ret = input_register_device(info->input); ++ if (ret) { ++ dev_err(&pdev->dev, "Can't register input device: %d\n", ret); ++ goto err_hpdet; ++ } + } + + pm_runtime_put(&pdev->dev); +@@ -1792,6 +1809,7 @@ static int arizona_extcon_remove(struct platform_device *pdev) + ARIZONA_JD1_ENA, 0); + arizona_clk32k_disable(arizona); + ++ input_put_device(info->input); + gpiod_put(info->micd_pol_gpio); + + pm_runtime_disable(&pdev->dev); +-- +2.28.0 + diff --git a/patches/ayame/0012-ASoC-Intel-Add-DMI-quirk-table-to-soc_intel_is_byt_c.patch b/patches/ayame/0012-ASoC-Intel-Add-DMI-quirk-table-to-soc_intel_is_byt_c.patch new file mode 100644 index 0000000..10ee214 --- /dev/null +++ b/patches/ayame/0012-ASoC-Intel-Add-DMI-quirk-table-to-soc_intel_is_byt_c.patch @@ -0,0 +1,74 @@ +From ba9a97d8fcc4b07e4ef7ff988f6cac69ed2e0fef Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 21 Dec 2020 16:29:47 +0100 +Subject: [PATCH 12/14] 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. + +Signed-off-by: Hans de Goede +--- + 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 b07df3059926..a93987ab7f4d 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 + #include + #include + #include +@@ -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.28.0 + diff --git a/patches/ayame/0013-ASoC-Intel-bytcr_wm5102-Add-machine-driver-for-BYT-W.patch b/patches/ayame/0013-ASoC-Intel-bytcr_wm5102-Add-machine-driver-for-BYT-W.patch new file mode 100644 index 0000000..fb9f429 --- /dev/null +++ b/patches/ayame/0013-ASoC-Intel-bytcr_wm5102-Add-machine-driver-for-BYT-W.patch @@ -0,0 +1,599 @@ +From 260089d8e58990103a52d0fbba47afc9163a94f7 Mon Sep 17 00:00:00 2001 +From: Pierre-Louis Bossart +Date: Thu, 3 Dec 2020 11:56:44 -0600 +Subject: [PATCH 13/14] 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 + 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. + +Co-authored-by: Pierre-Louis Bossart +Signed-off-by: Pierre-Louis Bossart +Signed-off-by: Hans de Goede +--- + sound/soc/intel/boards/Kconfig | 12 + + sound/soc/intel/boards/Makefile | 2 + + sound/soc/intel/boards/bytcr_wm5102.c | 472 ++++++++++++++++++ + .../intel/common/soc-acpi-intel-byt-match.c | 16 + + 4 files changed, 502 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 c10c37803c67..4088e19eb6b4 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 SPI && 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 a58e4d22e9c8..86661357bd22 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 000000000000..7de09cb5c50e +--- /dev/null ++++ b/sound/soc/intel/boards/bytcr_wm5102.c +@@ -0,0 +1,472 @@ ++// 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 ++ * Loosely based on bytcr_rt5640.c which is: ++ * Copyright (C) 2014-2020 Intel Corp ++ * Author: Subhransu S. Prusty ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ASYNCCLK: %d\n", ret); ++ return ret; ++ } ++ ++ ret = snd_soc_component_set_sysclk(codec_component, ARIZONA_CLK_OPCLK, 0, ++ rate * sr_mult, SND_SOC_CLOCK_OUT); ++ if (ret) { ++ dev_err(codec_component->dev, "Error setting OPCLK: %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 "); ++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 c348607b49a5..ec7932549655 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.28.0 + diff --git a/patches/ayame/0014-ASoC-Intel-bytcr_wm5102-Add-jack-detect-support.patch b/patches/ayame/0014-ASoC-Intel-bytcr_wm5102-Add-jack-detect-support.patch new file mode 100644 index 0000000..5b69edd --- /dev/null +++ b/patches/ayame/0014-ASoC-Intel-bytcr_wm5102-Add-jack-detect-support.patch @@ -0,0 +1,123 @@ +From 0070a092a0e9febbd370c6e63412b8b2317b777c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 23 Dec 2020 13:11:15 +0100 +Subject: [PATCH 14/14] ASoC: Intel: bytcr_wm5102: Add jack detect support + +The Linux Arizona/WM5102 driver uses the MFD framework to create several +sub-devices for the WM5102 codec and then uses a driver per function. + +The jack-detect support for the WM5102 codec is handled by the +extcon-arizona driver. This driver exports info about the jack state +to userspace through the standard extcon sysfs class interface. + +But standard Linux userspace does not monitor/use the extcon sysfs +interface for jack-detection. + +The extcon-arizona driver can also report jack-detect state through +the standard ASoC jack interface. For this we need to create a +snd_soc_jack and pass this to the extcon-arizona driver through the +shared arizona data struct. + +The extcon-arizona code already depends on (waits for with -EPROBE_DEFER) +the snd_card being registered by the machine driver, so this does not +cause any ordering issues. + +Signed-off-by: Hans de Goede +--- + sound/soc/intel/boards/bytcr_wm5102.c | 36 ++++++++++++++++++++++++++- + 1 file changed, 35 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c +index 7de09cb5c50e..25c7a6cacaad 100644 +--- a/sound/soc/intel/boards/bytcr_wm5102.c ++++ b/sound/soc/intel/boards/bytcr_wm5102.c +@@ -13,11 +13,13 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -31,6 +33,8 @@ + #define WM5102_MAX_SYSCLK_11025 45158400 /* max sysclk for 11.025K family */ + + struct byt_wm5102_private { ++ struct snd_soc_jack jack; ++ struct arizona *arizona; + struct clk *mclk; + struct gpio_desc *spkvdd_en_gpio; + }; +@@ -184,11 +188,22 @@ static const struct snd_kcontrol_new byt_wm5102_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), + }; + ++static struct snd_soc_jack_pin byt_wm5102_pins[] = { ++ { ++ .pin = "Headphone", ++ .mask = SND_JACK_HEADPHONE, ++ }, ++ { ++ .pin = "Headset Mic", ++ .mask = SND_JACK_MICROPHONE, ++ }, ++}; ++ + 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; ++ int ret, jack_type; + + card->dapm.idle_bias_off = true; + +@@ -217,6 +232,22 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) + return ret; + } + ++ jack_type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | ++ SND_JACK_BTN_2 | SND_JACK_BTN_3; ++ ret = snd_soc_card_jack_new(card, "Headset", jack_type, ++ &priv->jack, byt_wm5102_pins, ++ ARRAY_SIZE(byt_wm5102_pins)); ++ if (ret) { ++ dev_err(card->dev, "Error creating jack: %d\n", ret); ++ return ret; ++ } ++ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); ++ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); ++ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); ++ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); ++ ++ priv->arizona->jack = &priv->jack; ++ + return 0; + } + +@@ -409,6 +440,8 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) + + /* 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); ++ ++ priv->arizona = dev_get_drvdata(codec_dev); + put_device(codec_dev); + + if (IS_ERR(priv->spkvdd_en_gpio)) +@@ -452,6 +485,7 @@ 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); + ++ priv->arizona->jack = NULL; + gpiod_put(priv->spkvdd_en_gpio); + return 0; + } +-- +2.28.0 +