[PATCH 0/2] ASoC: Intel: avs: Add support for max98927 codec
This series adds machine board for max98927 codec present on some Chromebook devices.
Amadeusz Sławiński (2): ASoC: Intel: avs: Add max98927 machine board ASoC: Intel: avs: Load max98927 on target platform
sound/soc/intel/avs/board_selection.c | 8 + sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/max98927.c | 236 ++++++++++++++++++++++++++ 4 files changed, 256 insertions(+) create mode 100644 sound/soc/intel/avs/boards/max98927.c
To support AVS-max98927 configuration add machine board connecting AVS platform component driver with max98927 codec one.
Reviewed-by: Cezary Rojewski cezary.rojewski@intel.com Signed-off-by: Amadeusz Sławiński amadeuszx.slawinski@linux.intel.com --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/max98927.c | 236 ++++++++++++++++++++++++++ 3 files changed, 248 insertions(+) create mode 100644 sound/soc/intel/avs/boards/max98927.c
diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 4d68e3ef992b..9bd40fdd9028 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -36,6 +36,16 @@ config SND_SOC_INTEL_AVS_MACH_I2S_TEST This adds support for I2S test-board which can be used to verify transfer over I2S interface with SSP loopback scenarios.
+config SND_SOC_INTEL_AVS_MACH_MAX98927 + tristate "max98927 I2S board" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_MAX98927 + help + This adds support for AVS with MAX98927 I2S codec configuration. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_MAX98357A tristate "max98357A I2S board" depends on I2C diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index bc75376d58c2..4d70b8d09ce5 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -4,6 +4,7 @@ snd-soc-avs-da7219-objs := da7219.o snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o +snd-soc-avs-max98927-objs := max98927.o snd-soc-avs-max98357a-objs := max98357a.o snd-soc-avs-max98373-objs := max98373.o snd-soc-avs-nau8825-objs := nau8825.o @@ -17,6 +18,7 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DA7219) += snd-soc-avs-da7219.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_I2S_TEST) += snd-soc-avs-i2s-test.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98927) += snd-soc-avs-max98927.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A) += snd-soc-avs-max98357a.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98373) += snd-soc-avs-max98373.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c new file mode 100644 index 000000000000..35c4f8f55035 --- /dev/null +++ b/sound/soc/intel/avs/boards/max98927.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski cezary.rojewski@intel.com +// Amadeusz Slawinski amadeuszx.slawinski@linux.intel.com +// + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> + +#define MAX98927_DEV0_NAME "i2c-MX98927:00" +#define MAX98927_DEV1_NAME "i2c-MX98927:01" +#define MAX98927_CODEC_NAME "max98927-aif1" + +static struct snd_soc_codec_conf card_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF(MAX98927_DEV0_NAME), + .name_prefix = "Right", + }, + { + .dlc = COMP_CODEC_CONF(MAX98927_DEV1_NAME), + .name_prefix = "Left", + }, +}; + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + { "Left Spk", NULL, "Left BE_OUT" }, + { "Right Spk", NULL, "Right BE_OUT" }, +}; + +static int +avs_max98927_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will covert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 16 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + return 0; +} + +static int avs_max98927_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int ret = 0; + int i; + + for_each_rtd_codec_dais(runtime, i, codec_dai) { + if (!strcmp(codec_dai->component->name, MAX98927_DEV0_NAME)) + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); + else if (!strcmp(codec_dai->component->name, MAX98927_DEV1_NAME)) + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); + + if (ret < 0) { + dev_err(runtime->dev, "hw_params for %s failed: %d\n", + codec_dai->component->name, ret); + return ret; + } + } + + return 0; +} + +static const struct snd_soc_ops avs_max98927_ops = { + .hw_params = avs_max98927_hw_params, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs[0].name = devm_kasprintf(dev, GFP_KERNEL, MAX98927_DEV0_NAME); + dl->codecs[0].dai_name = devm_kasprintf(dev, GFP_KERNEL, MAX98927_CODEC_NAME); + dl->codecs[1].name = devm_kasprintf(dev, GFP_KERNEL, MAX98927_DEV1_NAME); + dl->codecs[1].dai_name = devm_kasprintf(dev, GFP_KERNEL, MAX98927_CODEC_NAME); + if (!dl->cpus->dai_name || !dl->codecs[0].name || !dl->codecs[0].dai_name || + !dl->codecs[1].name || !dl->codecs[1].dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 2; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->be_hw_params_fixup = avs_max98927_be_fixup; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + dl->ignore_pmdown_time = 1; + dl->ops = &avs_max98927_ops; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Left HiFi Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Right HiFi Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_max98927_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = "avs_max98927"; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = dai_link; + card->num_links = 1; + card->codec_conf = card_codec_conf; + card->num_configs = ARRAY_SIZE(card_codec_conf); + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_max98927_driver = { + .probe = avs_max98927_probe, + .driver = { + .name = "avs_max98927", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_max98927_driver) + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_max98927");
In order to load proper board configuration it needs to be looked up in ACPI. Add board configuration for MAXIM 98927 codec present on Chromebooks.
Reviewed-by: Cezary Rojewski cezary.rojewski@intel.com Signed-off-by: Amadeusz Sławiński amadeuszx.slawinski@linux.intel.com --- sound/soc/intel/avs/board_selection.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 87f9c18be238..1a85349f9563 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -121,6 +121,14 @@ static struct snd_soc_acpi_mach avs_kbl_i2s_machines[] = { .machine_quirk = dmi_match_quirk, .tplg_filename = "rt298-tplg.bin", }, + { + .id = "MX98927", + .drv_name = "avs_max98927", + .mach_params = { + .i2s_link_mask = AVS_SSP(0), + }, + .tplg_filename = "max98927-tplg.bin", + }, { .id = "MX98373", .drv_name = "avs_max98373",
On Fri, 30 Sep 2022 14:45:36 +0200, Amadeusz Sławiński wrote:
This series adds machine board for max98927 codec present on some Chromebook devices.
Amadeusz Sławiński (2): ASoC: Intel: avs: Add max98927 machine board ASoC: Intel: avs: Load max98927 on target platform
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/2] ASoC: Intel: avs: Add max98927 machine board commit: 1c993300ab1cec9a0a6a3c417614a1d9f35b175b [2/2] ASoC: Intel: avs: Load max98927 on target platform commit: 999ce9967a2f5a64c4bd04ae1edf0a979cf68833
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Amadeusz Sławiński
-
Mark Brown