test
This commit is contained in:
parent
ed0caaa09c
commit
ec5df91bee
29
ayame.nix
29
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;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,52 @@
|
||||
From 050388b1503e895deeff7f95bbdc3efb3d712aa2 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,62 @@
|
||||
From 9c530723d4a82322c072079e78d2ce856d6dcdc1 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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 <broonie@opensource.wolfsonmicro.com>");
|
||||
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 <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,192 @@
|
||||
From 73c418d5f8f0edbdeae3a47a0c916961decf5fdc Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <cornogle@googlemail.com>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
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 <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,119 @@
|
||||
#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;
|
||||
+ 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
|
||||
|
@ -0,0 +1,87 @@
|
||||
From f9112e46b682e21fa26488ce4d5794edaf850837 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,86 @@
|
||||
From c85886b2901593aef688b0c7a6a3b66222e99a90 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,122 @@
|
||||
From 2bc945b3018a3e5bac56e762c721447e804d6119 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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
|
||||
|
29
patches/ayame/0007-extcon-arizona-Fix-modalias.patch
Normal file
29
patches/ayame/0007-extcon-arizona-Fix-modalias.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From 399f229249269addcb5aba4c54d920d7c66955ed Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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 <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
-MODULE_ALIAS("platform:extcon-arizona");
|
||||
+MODULE_ALIAS("platform:arizona-extcon");
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,32 @@
|
||||
From 72d8e5732bc962b46dfbdc767ae6f7c5804e95c3 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,119 @@
|
||||
From bf992404b91f0283feb436dfb60e692763608cda Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,62 @@
|
||||
From e827a5cac13500bab604e1a3d410fb8910dad62c Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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 <linux/regulator/consumer.h>
|
||||
#include <linux/extcon-provider.h>
|
||||
|
||||
+#include <sound/jack.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include <linux/mfd/arizona/core.h>
|
||||
@@ -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
|
||||
|
@ -0,0 +1,110 @@
|
||||
From 72dbb22e561863e77fe07a12d03ed815d5e6a371 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,74 @@
|
||||
From ba9a97d8fcc4b07e4ef7ff988f6cac69ed2e0fef Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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 <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.28.0
|
||||
|
@ -0,0 +1,599 @@
|
||||
From 260089d8e58990103a52d0fbba47afc9163a94f7 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
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
|
||||
<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.
|
||||
|
||||
Co-authored-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
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 <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 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 <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 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
|
||||
|
@ -0,0 +1,123 @@
|
||||
From 0070a092a0e9febbd370c6e63412b8b2317b777c Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
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 <hdegoede@redhat.com>
|
||||
---
|
||||
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 <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
+#include <linux/input.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/jack.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
@@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user