From: Andy Shevchenko <andy.shevchenko@gmail.com>
To: Charles Keepax <ckeepax@opensource.cirrus.com>
Cc: broonie@kernel.org, linus.walleij@linaro.org, brgl@bgdev.pl,
linux-gpio@vger.kernel.org, linux-spi@vger.kernel.org,
patches@opensource.cirrus.com
Subject: Re: [PATCH v3 3/3] spi: cs42l43: Add bridged cs35l56 amplifiers
Date: Wed, 3 Apr 2024 23:47:36 +0300 [thread overview]
Message-ID: <Zg3AaNM0eizfC6Bk@surfacebook.localdomain> (raw)
In-Reply-To: <20240329114730.360313-4-ckeepax@opensource.cirrus.com>
Fri, Mar 29, 2024 at 11:47:30AM +0000, Charles Keepax kirjoitti:
> From: Maciej Strozek <mstrozek@opensource.cirrus.com>
>
> On some cs42l43 systems a couple of cs35l56 amplifiers are attached
> to the cs42l43's SPI and I2S. On Windows the cs42l43 is controlled
> by a SDCA class driver and these two amplifiers are controlled by
> firmware running on the cs42l43. However, under Linux the decision
> was made to interact with the cs42l43 directly, affording the user
> greater control over the audio system. However, this has resulted
> in an issue where these two bridged cs35l56 amplifiers are not
> populated in ACPI and must be added manually.
>
> Check for the presence of the "01fa-cirrus-sidecar-instances" property
> in the SDCA extension unit's ACPI properties to confirm the presence
> of these two amplifiers and if they exist add them manually onto the
> SPI bus.
...
> +#include <dt-bindings/gpio/gpio.h>
Hmm... Is it requirement by gpiolib-swnode? (I haven't looked at the use cases,
I'm not the author of this idea, hence the Q).
> +#include <linux/acpi.h>
You need array_size.h (and perhaps overflow.h) and property.h.
...
> +static struct spi_board_info ampl_info = {
> + .modalias = "cs35l56",
> + .max_speed_hz = 2000000,
Maybe HZ_PER_MHZ from units.h?
> + .chip_select = 0,
> + .mode = SPI_MODE_0,
> + .swnode = &l,
> + .use_fwnode_name = true,
> +};
> +
> +static struct spi_board_info ampr_info = {
> + .modalias = "cs35l56",
> + .max_speed_hz = 2000000,
Ditto.
> + .chip_select = 1,
> + .mode = SPI_MODE_0,
> + .swnode = &r,
> + .use_fwnode_name = true,
> +};
...
> +static const struct software_node_ref_args cs42l43_cs_refs[] = {
Please, use SOFTWARE_NODE_REFERENCE().
> + {
> + .node = &cs42l43_gpiochip_swnode,
> + .nargs = 2,
> + .args = { 0, GPIO_ACTIVE_LOW },
> + },
> + {
> + .node = &swnode_gpio_undefined,
> + .nargs = 0,
> + },
> +};
> +
> +static const struct property_entry cs42l43_cs_props[] = {
> + {
> + .name = "cs-gpios",
> + .length = ARRAY_SIZE(cs42l43_cs_refs) *
> + sizeof(struct software_node_ref_args),
> + .type = DEV_PROP_REF,
> + .pointer = cs42l43_cs_refs,
> + },
You want PROPERTY_ENTRY_REF_ARRAY()..
> + {}
> +};
...
> +#if IS_ENABLED(CONFIG_ACPI)
No need (see below)?
> +static bool cs42l43_has_sidecar(struct fwnode_handle *fwnode)
> +{
> + static const int func_smart_amp = 0x1;
> + struct fwnode_handle *child_fwnode, *ext_fwnode;
> + unsigned long long function;
> + unsigned int val;
> + int ret;
> + if (!is_acpi_node(fwnode))
> + return false;
Dup, your loop will perform the same effectivelly.
> + fwnode_for_each_child_node(fwnode, child_fwnode) {
> + struct acpi_device *adev = to_acpi_device_node(child_fwnode);
> +
> + ret = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &function);
> + if (ACPI_FAILURE(ret) || function != func_smart_amp) {
> + fwnode_handle_put(fwnode);
> + continue;
> + }
acpi_get_local_address() (it has a stub for CONFIG_ACPI=n).
> + ext_fwnode = fwnode_get_named_child_node(child_fwnode,
> + "mipi-sdca-function-expansion-subproperties");
> + if (!ext_fwnode) {
> + fwnode_handle_put(fwnode);
Are you sure?
> + continue;
> + }
> +
> + ret = fwnode_property_read_u32(ext_fwnode,
> + "01fa-cirrus-sidecar-instances",
> + &val);
> +
> + fwnode_handle_put(ext_fwnode);
> + fwnode_handle_put(fwnode);
Are you sure?
> + if (!ret)
> + return !!val;
> + }
> +
> + return false;
> +}
...
> - device_set_node(&priv->ctlr->dev, fwnode);
> + if (has_sidecar) {
> + ret = software_node_register(&cs42l43_gpiochip_swnode);
> + if (ret) {
> + dev_err(priv->dev, "Failed to register gpio swnode: %d\n", ret);
> + return ret;
> + }
> + ret = device_create_managed_software_node(&priv->ctlr->dev, cs42l43_cs_props, NULL);
No, this must not be used (I'm talking about _managed variant), this is a hack
for backward compatibility.
> + if (ret) {
> + dev_err(priv->dev, "Failed to add swnode: %d\n", ret);
> + goto err;
> + }
> +
Redundant blank line.
> + } else {
> + device_set_node(&priv->ctlr->dev, fwnode);
> + }
>
> ret = devm_spi_register_controller(priv->dev, priv->ctlr);
> if (ret) {
> dev_err(priv->dev, "Failed to register SPI controller: %d\n", ret);
> + goto err;
> + }
> +
> + if (has_sidecar) {
> + if (!spi_new_device(priv->ctlr, &l_info)) {
> + ret = -ENODEV;
> + dev_err(priv->dev, "Failed to create left amp slave\n");
> + goto err;
> + }
> +
> + if (!spi_new_device(priv->ctlr, &r_info)) {
> + ret = -ENODEV;
> + dev_err(priv->dev, "Failed to create right amp slave\n");
> + goto err;
> + }
> }
>
> + return 0;
> +
> +err:
> + if (has_sidecar)
> + software_node_unregister(&cs42l43_gpiochip_swnode);
> +
> return ret;
> }
Wondering why don't you use return dev_err_probe() / ret = dev_err_probe() /
dev_err_probe(ret)?
> +static int cs42l43_spi_remove(struct platform_device *pdev)
> +{
> + struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent);
platform_get_drvdata()
> + struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev);
Is this dev the same as &pdev->dev?
> + bool has_sidecar = cs42l43_has_sidecar(fwnode);
> +
> + if (has_sidecar)
> + software_node_unregister(&cs42l43_gpiochip_swnode);
> +
> + return 0;
> +};
--
With Best Regards,
Andy Shevchenko
next prev parent reply other threads:[~2024-04-03 20:47 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-29 11:47 [PATCH 0/3] Add bridged amplifiers to cs42l43 Charles Keepax
2024-03-29 11:47 ` [PATCH v3 1/3] gpio: swnode: Add ability to specify native chip selects for SPI Charles Keepax
2024-04-03 20:21 ` Andy Shevchenko
2024-03-29 11:47 ` [PATCH v3 2/3] spi: Add a mechanism to use the fwnode name for the SPI device Charles Keepax
2024-04-03 20:29 ` Andy Shevchenko
2024-04-08 13:51 ` Charles Keepax
2024-04-08 16:11 ` Andy Shevchenko
2024-03-29 11:47 ` [PATCH v3 3/3] spi: cs42l43: Add bridged cs35l56 amplifiers Charles Keepax
2024-04-03 20:47 ` Andy Shevchenko [this message]
2024-04-08 15:35 ` Charles Keepax
2024-04-08 16:07 ` Andy Shevchenko
2024-04-08 19:50 ` Andy Shevchenko
2024-04-08 20:07 ` Andy Shevchenko
2024-04-09 9:24 ` Charles Keepax
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zg3AaNM0eizfC6Bk@surfacebook.localdomain \
--to=andy.shevchenko@gmail.com \
--cc=brgl@bgdev.pl \
--cc=broonie@kernel.org \
--cc=ckeepax@opensource.cirrus.com \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=patches@opensource.cirrus.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox