Skip to content

Commit 0dae534

Browse files
krzkbroonie
authored andcommitted
ASoC: codecs: wsa884x: Allow sharing reset GPIO
On some boards with multiple WSA8840/WSA8845 speakers, the reset (shutdown) GPIO is shared between two speakers. Use the reset controller framework and its "reset-gpio" driver to handle this case. This allows bring-up and proper handling of all WSA884x speakers on X1E80100-CRD board. Cc: Bartosz Golaszewski <[email protected]> Cc: Sean Anderson <[email protected]> Reviewed-by: Philipp Zabel <[email protected]> Signed-off-by: Krzysztof Kozlowski <[email protected]> Link: https://msgid.link/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 26c8a43 commit 0dae534

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

sound/soc/codecs/wsa884x.c

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/pm_runtime.h>
1414
#include <linux/regmap.h>
1515
#include <linux/regulator/consumer.h>
16+
#include <linux/reset.h>
1617
#include <linux/slab.h>
1718
#include <linux/soundwire/sdw.h>
1819
#include <linux/soundwire/sdw_registers.h>
@@ -699,6 +700,7 @@ struct wsa884x_priv {
699700
struct sdw_stream_runtime *sruntime;
700701
struct sdw_port_config port_config[WSA884X_MAX_SWR_PORTS];
701702
struct gpio_desc *sd_n;
703+
struct reset_control *sd_reset;
702704
bool port_prepared[WSA884X_MAX_SWR_PORTS];
703705
bool port_enable[WSA884X_MAX_SWR_PORTS];
704706
unsigned int variant;
@@ -1799,16 +1801,50 @@ static struct snd_soc_dai_driver wsa884x_dais[] = {
17991801
},
18001802
};
18011803

1802-
static void wsa884x_gpio_powerdown(void *data)
1804+
static void wsa884x_reset_powerdown(void *data)
18031805
{
1804-
gpiod_direction_output(data, 1);
1806+
struct wsa884x_priv *wsa884x = data;
1807+
1808+
if (wsa884x->sd_reset)
1809+
reset_control_assert(wsa884x->sd_reset);
1810+
else
1811+
gpiod_direction_output(wsa884x->sd_n, 1);
1812+
}
1813+
1814+
static void wsa884x_reset_deassert(struct wsa884x_priv *wsa884x)
1815+
{
1816+
if (wsa884x->sd_reset)
1817+
reset_control_deassert(wsa884x->sd_reset);
1818+
else
1819+
gpiod_direction_output(wsa884x->sd_n, 0);
18051820
}
18061821

18071822
static void wsa884x_regulator_disable(void *data)
18081823
{
18091824
regulator_bulk_disable(WSA884X_SUPPLIES_NUM, data);
18101825
}
18111826

1827+
static int wsa884x_get_reset(struct device *dev, struct wsa884x_priv *wsa884x)
1828+
{
1829+
wsa884x->sd_reset = devm_reset_control_get_optional_shared(dev, NULL);
1830+
if (IS_ERR(wsa884x->sd_reset))
1831+
return dev_err_probe(dev, PTR_ERR(wsa884x->sd_reset),
1832+
"Failed to get reset\n");
1833+
else if (wsa884x->sd_reset)
1834+
return 0;
1835+
/*
1836+
* else: NULL, so use the backwards compatible way for powerdown-gpios,
1837+
* which does not handle sharing GPIO properly.
1838+
*/
1839+
wsa884x->sd_n = devm_gpiod_get_optional(dev, "powerdown",
1840+
GPIOD_OUT_HIGH);
1841+
if (IS_ERR(wsa884x->sd_n))
1842+
return dev_err_probe(dev, PTR_ERR(wsa884x->sd_n),
1843+
"Shutdown Control GPIO not found\n");
1844+
1845+
return 0;
1846+
}
1847+
18121848
static int wsa884x_probe(struct sdw_slave *pdev,
18131849
const struct sdw_device_id *id)
18141850
{
@@ -1838,11 +1874,9 @@ static int wsa884x_probe(struct sdw_slave *pdev,
18381874
if (ret)
18391875
return ret;
18401876

1841-
wsa884x->sd_n = devm_gpiod_get_optional(dev, "powerdown",
1842-
GPIOD_OUT_HIGH);
1843-
if (IS_ERR(wsa884x->sd_n))
1844-
return dev_err_probe(dev, PTR_ERR(wsa884x->sd_n),
1845-
"Shutdown Control GPIO not found\n");
1877+
ret = wsa884x_get_reset(dev, wsa884x);
1878+
if (ret)
1879+
return ret;
18461880

18471881
dev_set_drvdata(dev, wsa884x);
18481882
wsa884x->slave = pdev;
@@ -1858,9 +1892,8 @@ static int wsa884x_probe(struct sdw_slave *pdev,
18581892
pdev->prop.sink_dpn_prop = wsa884x_sink_dpn_prop;
18591893
pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
18601894

1861-
/* Bring out of reset */
1862-
gpiod_direction_output(wsa884x->sd_n, 0);
1863-
ret = devm_add_action_or_reset(dev, wsa884x_gpio_powerdown, wsa884x->sd_n);
1895+
wsa884x_reset_deassert(wsa884x);
1896+
ret = devm_add_action_or_reset(dev, wsa884x_reset_powerdown, wsa884x);
18641897
if (ret)
18651898
return ret;
18661899

0 commit comments

Comments
 (0)