Hi Simon, On Wed, Jul 8, 2020 at 11:33 AM Simon Glass <s...@chromium.org> wrote: > > This chip is used on coral and we need to generate ACPI tables for sound > to make it work. Add a driver that does just this (i.e. at present does > not actually support playing sound). > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > Changes in v2: > Add a comment about only x86 boards supporting NHLT > > Changes in v1: > - Use acpi,ddn instead of acpi,desc > - Drop the unwanted acpi_device_write_gpio_desc() > - Rename max97357a to max98357a > - Add NHLT support > - Capitalise ACPI_OPS_PTR > - Rebase to master > > configs/sandbox_defconfig | 1 + > doc/device-tree-bindings/sound/max98357a.txt | 22 +++ > drivers/sound/Kconfig | 9 ++ > drivers/sound/Makefile | 1 + > drivers/sound/max98357a.c | 161 +++++++++++++++++++ > 5 files changed, 194 insertions(+) > create mode 100644 doc/device-tree-bindings/sound/max98357a.txt > create mode 100644 drivers/sound/max98357a.c > > diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig > index 3817091d02..0c9524ff6c 100644 > --- a/configs/sandbox_defconfig > +++ b/configs/sandbox_defconfig > @@ -207,6 +207,7 @@ CONFIG_SMEM=y > CONFIG_SANDBOX_SMEM=y > CONFIG_SOUND=y > CONFIG_SOUND_DA7219=y > +CONFIG_SOUND_MAX98357A=y > CONFIG_SOUND_SANDBOX=y > CONFIG_SANDBOX_SPI=y > CONFIG_SPMI=y > diff --git a/doc/device-tree-bindings/sound/max98357a.txt > b/doc/device-tree-bindings/sound/max98357a.txt > new file mode 100644 > index 0000000000..4bce14ce80 > --- /dev/null > +++ b/doc/device-tree-bindings/sound/max98357a.txt > @@ -0,0 +1,22 @@ > +Maxim MAX98357A audio DAC > + > +This node models the Maxim MAX98357A DAC. > + > +Required properties: > +- compatible : "maxim,max98357a" > + > +Optional properties: > +- sdmode-gpios : GPIO specifier for the chip's SD_MODE pin. > + If this option is not specified then driver does not manage > + the pin state (e.g. chip is always on). > +- sdmode-delay : specify delay time for SD_MODE pin. > + If this option is specified, which means it's required i2s clocks > + ready before SD_MODE is unmuted in order to avoid the speaker pop > noise. > + It's observed that 5ms is sufficient. > + > +Example: > + > +max98357a { > + compatible = "maxim,max98357a"; > + sdmode-gpios = <&qcom_pinmux 25 0>; > +}; > diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig > index 7f214b97be..0948d8caab 100644 > --- a/drivers/sound/Kconfig > +++ b/drivers/sound/Kconfig > @@ -113,6 +113,15 @@ config SOUND_MAX98095 > audio data and I2C for codec control. At present it only works > with the Samsung I2S driver. > > +config SOUND_MAX98357A > + bool "Support Maxim max98357a audio codec" > + depends on PCI > + help > + Enable the max98357a audio codec. This is connected on PCI for > + audio data codec control. This is currently only capable of > providing > + ACPI information. A full driver (with sound in U-Boot) is currently > + not available. > + > config SOUND_RT5677 > bool "Support Realtek RT5677 audio codec" > depends on SOUND > diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile > index 8c3933ad15..9b40c8012f 100644 > --- a/drivers/sound/Makefile > +++ b/drivers/sound/Makefile > @@ -17,6 +17,7 @@ obj-$(CONFIG_SOUND_WM8994) += wm8994.o > obj-$(CONFIG_SOUND_MAX98088) += max98088.o maxim_codec.o > obj-$(CONFIG_SOUND_MAX98090) += max98090.o maxim_codec.o > obj-$(CONFIG_SOUND_MAX98095) += max98095.o maxim_codec.o > +obj-$(CONFIG_SOUND_MAX98357A) += max98357a.o > obj-$(CONFIG_SOUND_INTEL_HDA) += hda_codec.o > obj-$(CONFIG_SOUND_I8254) += i8254_beep.o > obj-$(CONFIG_SOUND_RT5677) += rt5677.o > diff --git a/drivers/sound/max98357a.c b/drivers/sound/max98357a.c > new file mode 100644 > index 0000000000..827262d235 > --- /dev/null > +++ b/drivers/sound/max98357a.c > @@ -0,0 +1,161 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * max98357a.c -- MAX98357A Audio driver > + * > + * Copyright 2019 Google LLC > + * Parts taken from coreboot > + */ > + > +#include <common.h> > +#include <audio_codec.h> > +#include <dm.h> > +#include <log.h> > +#include <sound.h> > +#include <acpi/acpigen.h> > +#include <acpi/acpi_device.h> > +#include <acpi/acpi_dp.h> > +#include <asm-generic/gpio.h> > +#ifdef CONFIG_X86 > +#include <asm/acpi_nhlt.h> > +#endif > +#include <dt-bindings/sound/nhlt.h> > +#include <dm/acpi.h> > + > +struct max98357a_priv { > + struct gpio_desc sdmode_gpio; > +}; > + > +static int max98357a_ofdata_to_platdata(struct udevice *dev) > +{ > + struct max98357a_priv *priv = dev_get_priv(dev); > + int ret; > + > + ret = gpio_request_by_name(dev, "sdmode-gpios", 0, &priv->sdmode_gpio, > + GPIOD_IS_IN); > + if (ret) > + return log_msg_ret("gpio", ret); > + > + return 0; > +} > + > +static int max98357a_acpi_fill_ssdt(const struct udevice *dev, > + struct acpi_ctx *ctx) > +{ > + struct max98357a_priv *priv = dev_get_priv(dev); > + char scope[ACPI_PATH_MAX]; > + char name[ACPI_NAME_MAX]; > + char path[ACPI_PATH_MAX]; > + struct acpi_dp *dp; > + int ret; > + > + ret = acpi_device_scope(dev, scope, sizeof(scope)); > + if (ret) > + return log_msg_ret("scope", ret); > + ret = acpi_get_name(dev, name); > + if (ret) > + return log_msg_ret("name", ret); > + > + /* Device */ > + acpigen_write_scope(ctx, scope); > + acpigen_write_device(ctx, name); > + acpigen_write_name_string(ctx, "_HID", > + dev_read_string(dev, "acpi,hid")); > + acpigen_write_name_integer(ctx, "_UID", 0); > + acpigen_write_name_string(ctx, "_DDN", > + dev_read_string(dev, "acpi,ddn")); > + acpigen_write_sta(ctx, acpi_device_status(dev)); > + > + /* Resources */ > + acpigen_write_name(ctx, "_CRS"); > + acpigen_write_resourcetemplate_header(ctx); > + ret = acpi_device_write_gpio_desc(ctx, &priv->sdmode_gpio); > + if (ret) > + return log_msg_ret("gpio", ret); > + acpigen_write_resourcetemplate_footer(ctx); > + > + /* _DSD for devicetree properties */ > + /* This points to the first pin in the first gpio entry in _CRS */ > + ret = acpi_device_path(dev, path, sizeof(path)); > + if (ret) > + return log_msg_ret("path", ret); > + dp = acpi_dp_new_table("_DSD"); > + acpi_dp_add_gpio(dp, "sdmode-gpio", path, 0, 0, > + priv->sdmode_gpio.flags & GPIOD_ACTIVE_LOW ? > + ACPI_GPIO_ACTIVE_LOW : ACPI_GPIO_ACTIVE_HIGH);
There is a bug here: It should be: ACPI_IRQ_ACTIVE_LOW : ACPI_IRQ_ACTIVE_HIGH I also noticed that ACPI_IRQ_ACTIVE_LOW value is 0 but ACPI_GPIO_ACTIVE_LOW value is 1. Is this intentional? Please suggest how to fix this, so I can apply the fix locally. Currently this is the only failure that was reported by CI pipelines. > + acpi_dp_add_integer(dp, "sdmode-delay", > + dev_read_u32_default(dev, "sdmode-delay", 0)); > + acpi_dp_write(ctx, dp); > + > + acpigen_pop_len(ctx); /* Device */ > + acpigen_pop_len(ctx); /* Scope */ > + > + return 0; > +} > + > +/* For now only X86 boards support NHLT */ > +#ifdef CONFIG_X86 > +static const struct nhlt_format_config max98357a_formats[] = { > + /* 48 KHz 24-bits per sample. */ > + { > + .num_channels = 2, > + .sample_freq_khz = 48, > + .container_bits_per_sample = 32, > + .valid_bits_per_sample = 24, > + .settings_file = "max98357-render-2ch-48khz-24b.dat", > + }, > +}; > + > +static const struct nhlt_endp_descriptor max98357a_descriptors[] = { > + { > + .link = NHLT_LINK_SSP, > + .device = NHLT_SSP_DEV_I2S, > + .direction = NHLT_DIR_RENDER, > + .vid = NHLT_VID, > + .did = NHLT_DID_SSP, > + .formats = max98357a_formats, > + .num_formats = ARRAY_SIZE(max98357a_formats), > + }, > +}; > + > +static int max98357a_acpi_setup_nhlt(const struct udevice *dev, > + struct acpi_ctx *ctx) > +{ > + u32 hwlink; > + int ret; > + > + if (dev_read_u32(dev, "acpi,audio-link", &hwlink)) > + return log_msg_ret("link", -EINVAL); > + > + /* Virtual bus id of SSP links are the hardware port ids proper. */ > + ret = nhlt_add_ssp_endpoints(ctx->nhlt, hwlink, max98357a_descriptors, > + ARRAY_SIZE(max98357a_descriptors)); > + if (ret) > + return log_msg_ret("add", ret); > + > + return 0; > +} > +#endif > + > +struct acpi_ops max98357a_acpi_ops = { > + .fill_ssdt = max98357a_acpi_fill_ssdt, > +#ifdef CONFIG_X86 > + .setup_nhlt = max98357a_acpi_setup_nhlt, > +#endif > +}; > + > +static const struct audio_codec_ops max98357a_ops = { > +}; > + > +static const struct udevice_id max98357a_ids[] = { > + { .compatible = "maxim,max98357a" }, > + { } > +}; > + > +U_BOOT_DRIVER(max98357a) = { > + .name = "max98357a", > + .id = UCLASS_AUDIO_CODEC, > + .of_match = max98357a_ids, > + .ofdata_to_platdata = max98357a_ofdata_to_platdata, > + .ops = &max98357a_ops, > + ACPI_OPS_PTR(&max98357a_acpi_ops) > +}; > -- Regards, Bin