From: Linus Walleij Date: Mon, 27 Apr 2026 08:43:21 +0000 (+0200) Subject: ASoC: wsa881x: Move custom workaround to gpiolib-of X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bfa336cee3324f991e93e9e570e8b827273df97e;p=thirdparty%2Fkernel%2Flinux.git ASoC: wsa881x: Move custom workaround to gpiolib-of 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 . Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20260427-asoc-wsa881x-v2-1-9ef965f94624@kernel.org Signed-off-by: Mark Brown --- diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 2c923d17541f2..90f6295ab3384 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -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; diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 2fc234adca5f7..d15fda648dada 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -3,7 +3,6 @@ // Copyright (c) 2019, Linaro Limited #include -#include #include #include #include @@ -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; }