diff options
author | Simon Trimmer <simont@opensource.cirrus.com> | 2024-06-19 15:17:03 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2024-06-20 23:10:15 +0300 |
commit | 0ca645ab5b1528666f6662a0e620140355b5aea3 (patch) | |
tree | 474f30e4fac8eff5747d81798b7529ebe1a704fc /drivers/spi | |
parent | cc169cf869fdac34531fd4d0e7317f0576883228 (diff) | |
download | linux-0ca645ab5b1528666f6662a0e620140355b5aea3.tar.xz |
spi: cs42l43: Add speaker id support to the bridge configuration
OEMs can connect a number of types of speakers to the sidecar cs35l56
amplifiers and a different speaker requires a different firmware
configuration.
When the cs42l43 ACPI includes a property indicating a particular type
of speaker has been installed this should be passed to the cs35l56
driver instances as a device property.
Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20240619121703.3411989-2-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-cs42l43.c | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c index 7b6fc6158a3b..5b8ed65f8094 100644 --- a/drivers/spi/spi-cs42l43.c +++ b/drivers/spi/spi-cs42l43.c @@ -45,28 +45,10 @@ static const unsigned int cs42l43_clock_divs[] = { 2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 }; -static const struct software_node ampl = { - .name = "cs35l56-left", -}; - -static const struct software_node ampr = { - .name = "cs35l56-right", -}; - -static struct spi_board_info ampl_info = { +static struct spi_board_info amp_info_template = { .modalias = "cs35l56", .max_speed_hz = 11 * HZ_PER_MHZ, - .chip_select = 0, .mode = SPI_MODE_0, - .swnode = &l, -}; - -static struct spi_board_info ampr_info = { - .modalias = "cs35l56", - .max_speed_hz = 11 * HZ_PER_MHZ, - .chip_select = 1, - .mode = SPI_MODE_0, - .swnode = &r, }; static const struct software_node cs42l43_gpiochip_swnode = { @@ -274,6 +256,39 @@ static struct fwnode_handle *cs42l43_find_xu_node(struct fwnode_handle *fwnode) return NULL; } +static struct spi_board_info *cs42l43_create_bridge_amp(struct cs42l43_spi *priv, + const char * const name, + int cs, int spkid) +{ + struct property_entry *props = NULL; + struct software_node *swnode; + struct spi_board_info *info; + + if (spkid >= 0) { + props = devm_kmalloc(priv->dev, sizeof(*props), GFP_KERNEL); + if (!props) + return NULL; + + *props = PROPERTY_ENTRY_U32("cirrus,speaker-id", spkid); + } + + swnode = devm_kmalloc(priv->dev, sizeof(*swnode), GFP_KERNEL); + if (!swnode) + return NULL; + + *swnode = SOFTWARE_NODE(name, props, NULL); + + info = devm_kmemdup(priv->dev, &_info_template, + sizeof(amp_info_template), GFP_KERNEL); + if (!info) + return NULL; + + info->chip_select = cs; + info->swnode = swnode; + + return info; +} + static void cs42l43_release_of_node(void *data) { fwnode_handle_put(data); @@ -368,11 +383,27 @@ static int cs42l43_spi_probe(struct platform_device *pdev) "Failed to register SPI controller\n"); if (nsidecars) { - if (!spi_new_device(priv->ctlr, &l_info)) + struct spi_board_info *ampl_info; + struct spi_board_info *ampr_info; + int spkid = -EINVAL; + + fwnode_property_read_u32(xu_fwnode, "01fa-spk-id-val", &spkid); + + dev_dbg(priv->dev, "Found speaker ID %d\n", spkid); + + ampl_info = cs42l43_create_bridge_amp(priv, "cs35l56-left", 0, spkid); + if (!ampl_info) + return -ENOMEM; + + ampr_info = cs42l43_create_bridge_amp(priv, "cs35l56-right", 1, spkid); + if (!ampr_info) + return -ENOMEM; + + if (!spi_new_device(priv->ctlr, ampl_info)) return dev_err_probe(priv->dev, -ENODEV, "Failed to create left amp slave\n"); - if (!spi_new_device(priv->ctlr, &r_info)) + if (!spi_new_device(priv->ctlr, ampr_info)) return dev_err_probe(priv->dev, -ENODEV, "Failed to create right amp slave\n"); } |