]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: wsa881x: Move custom workaround to gpiolib-of
authorLinus Walleij <linusw@kernel.org>
Mon, 27 Apr 2026 08:43:21 +0000 (10:43 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 27 Apr 2026 22:39:15 +0000 (07:39 +0900)
The WSA881x codec driver has a local workaround for old device
trees that have the "powerdown" GPIO flagged as active high,
despite it is active low.

This quirk can be replaced by a single quirk entry in
gpiolib-of.c

Drop all polarity inversion code and drop the surplus
gpiod_direction_output() call in probe() since we now set up
the line correctly when getting the GPIO.

Also drop the inclusion of the unused <linux/gpio.h>.

Signed-off-by: Linus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260427-asoc-wsa881x-v2-1-9ef965f94624@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/gpio/gpiolib-of.c
sound/soc/codecs/wsa881x.c

index 2c923d17541f26586d531713d7f1fc917cdceaf4..90f6295ab33842f8da549716ad9b8b2b809e7477 100644 (file)
@@ -240,6 +240,14 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
                 * treats it as "active low".
                 */
                { "ti,tsc2005",         "reset-gpios",  false },
+#endif
+#if IS_ENABLED(CONFIG_SND_SOC_WSA881X)
+               /*
+                * WSA881 powerdown is always active low, but some device trees
+                * missed this when first contributed. It also has a very strange
+                * compatible.
+                */
+               { "sdw10217201000",     "powerdown-gpios", false },
 #endif
        };
        unsigned int i;
index 2fc234adca5f7ee11afbc572bb36e8b948f6462e..d15fda648dadad7cc4eee08ba5c4acf19ea6f15f 100644 (file)
@@ -3,7 +3,6 @@
 // Copyright (c) 2019, Linaro Limited
 
 #include <linux/bitops.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
@@ -672,11 +671,6 @@ struct wsa881x_priv {
        struct sdw_stream_runtime *sruntime;
        struct sdw_port_config port_config[WSA881X_MAX_SWR_PORTS];
        struct gpio_desc *sd_n;
-       /*
-        * Logical state for SD_N GPIO: high for shutdown, low for enable.
-        * For backwards compatibility.
-        */
-       unsigned int sd_n_val;
        int active_ports;
        bool hw_init;
        bool port_prepared[WSA881X_MAX_SWR_PORTS];
@@ -1121,31 +1115,11 @@ static int wsa881x_probe(struct sdw_slave *pdev,
        if (!wsa881x)
                return -ENOMEM;
 
-       wsa881x->sd_n = devm_gpiod_get_optional(dev, "powerdown", 0);
+       wsa881x->sd_n = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_LOW);
        if (IS_ERR(wsa881x->sd_n))
                return dev_err_probe(dev, PTR_ERR(wsa881x->sd_n),
                                     "Shutdown Control GPIO not found\n");
 
-       /*
-        * Backwards compatibility work-around.
-        *
-        * The SD_N GPIO is active low, however upstream DTS used always active
-        * high.  Changing the flag in driver and DTS will break backwards
-        * compatibility, so add a simple value inversion to work with both old
-        * and new DTS.
-        *
-        * This won't work properly with DTS using the flags properly in cases:
-        * 1. Old DTS with proper ACTIVE_LOW, however such case was broken
-        *    before as the driver required the active high.
-        * 2. New DTS with proper ACTIVE_HIGH (intended), which is rare case
-        *    (not existing upstream) but possible. This is the price of
-        *    backwards compatibility, therefore this hack should be removed at
-        *    some point.
-        */
-       wsa881x->sd_n_val = gpiod_is_active_low(wsa881x->sd_n);
-       if (!wsa881x->sd_n_val)
-               dev_warn(dev, "Using ACTIVE_HIGH for shutdown GPIO. Your DTB might be outdated or you use unsupported configuration for the GPIO.");
-
        dev_set_drvdata(dev, wsa881x);
        wsa881x->slave = pdev;
        wsa881x->dev = dev;
@@ -1158,7 +1132,6 @@ static int wsa881x_probe(struct sdw_slave *pdev,
        pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
        pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
        pdev->prop.clk_stop_mode1 = true;
-       gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
 
        wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
        if (IS_ERR(wsa881x->regmap))
@@ -1181,7 +1154,7 @@ static int wsa881x_runtime_suspend(struct device *dev)
        struct regmap *regmap = dev_get_regmap(dev, NULL);
        struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
 
-       gpiod_direction_output(wsa881x->sd_n, wsa881x->sd_n_val);
+       gpiod_direction_output(wsa881x->sd_n, 1);
 
        regcache_cache_only(regmap, true);
        regcache_mark_dirty(regmap);
@@ -1196,13 +1169,13 @@ static int wsa881x_runtime_resume(struct device *dev)
        struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
        unsigned long time;
 
-       gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
+       gpiod_direction_output(wsa881x->sd_n, 0);
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                           msecs_to_jiffies(WSA881X_PROBE_TIMEOUT));
        if (!time) {
                dev_err(dev, "Initialization not complete, timed out\n");
-               gpiod_direction_output(wsa881x->sd_n, wsa881x->sd_n_val);
+               gpiod_direction_output(wsa881x->sd_n, 1);
                return -ETIMEDOUT;
        }