From patchwork Mon Nov 8 15:27:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Nazzareno Trimarchi X-Patchwork-Id: 1732 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id 1BD193F159 for ; Mon, 8 Nov 2021 16:27:50 +0100 (CET) Received: by mail-wr1-f69.google.com with SMTP id p17-20020adff211000000b0017b902a7701sf4150004wro.19 for ; Mon, 08 Nov 2021 07:27:50 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1636385269; cv=pass; d=google.com; s=arc-20160816; b=sqo44SerZkIauuHXuJuEJDsGy8lcFcEXcY6UZ9QU2nqEJNpAo1K93kOCJFxgvWHQkh bmI9dZvLpVJrleJFXWA6A97RZ8kd9sm/kq8Gpw/I5wi/1YPaNEzdQYqqsdr1Q21wWaR0 j9g9yt0pqBfR9QvAjw1zldCmWD1r0OkjQPKikt1UKtFoBzuM/BfB696RCdfj77+CtSE9 TFc4Zvh/b829wDC3eqMDiLbhwUMMDAsrHAtCjvHbKkfj9k3yqdN0VsGKKwB152JyOaCv RvuudATmJP8pTBr6FD3oH733TVtlP1qege4uxHZ7nI/bfX+2elGmnh2325tDh83L4jZY z4Bw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:mime-version:message-id:date:subject:cc:to :from:dkim-signature; bh=UZAND2P0f8ueuCfx9B+vIkjO629NAR7zp4sz5zNhdDY=; b=wEZVXiMoKMM7Lznz50QOdqJRKZS51namZw0YIscPsIaB01AOS170vbsEiJh4npbMjP jF/hsvXhCSy4V75Kn5/it4y3eZ1pb8g9YKALRRvBY1w3N5FfIs4aLck+JBxnq1eSyVvA ZH8yEN21AzgOwZqv6P+iBME17FXRyEptxx0ZRUB/qMTFpFBsl0UD+ZOBM0p90BSwz1rt rmTXnoVGevX65XKQl9HUtTo6rDj58CdaQXP83lfgURROcl5BGtahGVCZU/fqp0AYuTUm qPZ2US57DHlEkVnRmFWp0vf+bmIRyu6ec8tY/uGJSB3x0PpEBihQTGyAfZ5X+7nUNc4T pTFA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=F0W8JY0Z; spf=pass (google.com: domain of michael@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=michael@amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=from:to:cc:subject:date:message-id:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=UZAND2P0f8ueuCfx9B+vIkjO629NAR7zp4sz5zNhdDY=; b=PqNjBsuiw0Tq7CD0Id5xwDrZV+STZecPAVH4GXXseu9Bs3Q7tkBkpuOGHi2+7SifXG fec7IBA7o+zULBvb2qdApQSRWU+r6IvfKFQwEHr4jcToM3tMW0DYUG+vSf9AvX/WS604 wdK0hjcn7w92cqDzA4+HOl6YU69Het/V7Y/ys= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :x-original-sender:x-original-authentication-results:precedence :mailing-list:list-id:x-spam-checked-in-group:list-post:list-help :list-archive:list-unsubscribe; bh=UZAND2P0f8ueuCfx9B+vIkjO629NAR7zp4sz5zNhdDY=; b=jLH6Afl1ht7Ux9IObZvGAI4bHErFz5mxSw392zwPL2DsPQ/jZ0QNihq1n3licaaUqd KP40pzPDy9XK2nxE7asfU3YNsQyWldvATK3DqHgmferlrvsD58wQw22qaUV8i31vTR4N 2WQn+relNiH5o1EyxBSZQFU4xf+bEVNMOkPM1jeCNp17jym5aT3l1i44qpRKThV/6/Pd WHZw13UPbw3yrE6ES1S0qQq519fSKbjEwDN/SMgeGVRgWYZCGZC4CefJB0tI9UwjkxKH 7rP2NV4K54gZo5P6jghDWTIeLIaDZ/nhSi2int7cgvC89c19CVLfmdb+CiD+nLTUQEgQ rYMQ== X-Gm-Message-State: AOAM532+DzSpFVjXYKGggzVwCQBb7uQueRPkyw3A83O6B69dNdEZh/Vg Xj4jheSCsFtTzRol7n2fTMKmF5Nr X-Google-Smtp-Source: ABdhPJzevqC444/PcBrZB4vbd4rJbUOJztnxjj99hUQt6cZVMLIdFS7mnz7nI+X0sgZEFcaR4aTGdg== X-Received: by 2002:adf:cf05:: with SMTP id o5mr620124wrj.325.1636385269749; Mon, 08 Nov 2021 07:27:49 -0800 (PST) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a05:600c:3b8b:: with SMTP id n11ls3486695wms.2.canary-gmail; Mon, 08 Nov 2021 07:27:48 -0800 (PST) X-Received: by 2002:a05:600c:3b1b:: with SMTP id m27mr87009wms.125.1636385268527; Mon, 08 Nov 2021 07:27:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1636385268; cv=none; d=google.com; s=arc-20160816; b=zmDRoTPiy3m+GYdNvPQMGxgn9JhWfEcsGHugcZ3AATlgdgzrleHmsWOwT7pK52kM24 T5Li7TGZTpumgTMP2nrSBNrDt200nPCzl7s1i/dV7Mu1y3V3XMGOB5QJvgJ4Zk+9+/Bz ZiXqKZIRvcMv7dCrmVo7M1JJ11ZUbaUY9DhhKEutqkuCKqwjYiaj35VjBtJNn9SFU+OS EgTysGI9dvbNY9XVlTeS9gjNwFL2bX+gb+TMKqTJzaJn0dNxhhqwdGwOcZoR4EXK3r9g ArHZBALWKk3Rtq5/FR/3meFP8CbglqeFjBHMeUCnRYgcRnGlGU9tsrvcBD+wRtHGyP5X zZ9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:dkim-signature; bh=AkxPQ+zGtzjWUEvEDMFx6AuIxHT4FxOagW5HLsqAaLc=; b=cXyZxVhm8LfysOh5slxQfeCXutHrDSk2bZ5m2KptJIfDzeYb94nAWvKoD9yfgyD+44 DhNK3fcbvOgan6bGfKL8mx0cdMGuKJteXyI2f3X2wMfMuElOG/3+RNC91UAiBCsqglDK V2CDHaR3EWaPR+dSUlk1R4FwEPYEn7eixHsOokBXNRkCsy8Nddj90+XiEcvbwldGTEqW OWEAXvHkQI+g1/ELc6+0lx7Mxl7QupJC+Be1GO84BZ7jy3I36QtMYT2Jk/iqtCry60ud 8mxci+n6tCVAAF8FJMe2E9yeK7aLdxjYZNRkYT3rUtDaAPzaNiV4rjNuiKCWBkBGsGFC ngUA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=F0W8JY0Z; spf=pass (google.com: domain of michael@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=michael@amarulasolutions.com Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id p22sor9284034wmi.21.2021.11.08.07.27.48 for (Google Transport Security); Mon, 08 Nov 2021 07:27:48 -0800 (PST) Received-SPF: pass (google.com: domain of michael@amarulasolutions.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; X-Received: by 2002:a1c:80c5:: with SMTP id b188mr102657wmd.57.1636385268129; Mon, 08 Nov 2021 07:27:48 -0800 (PST) Received: from panicking.amarulasolutions.com ([2.198.173.211]) by smtp.gmail.com with ESMTPSA id y10sm21549729wrd.84.2021.11.08.07.27.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Nov 2021 07:27:47 -0800 (PST) From: Michael Trimarchi To: Ariel D'Alessandro Cc: linux-amarula@amarulasolutions.com, Anthony Brandon Subject: [PATCH V2 1/3] ASoC: fsl: add smm-s2-pro audio driver Date: Mon, 8 Nov 2021 16:27:43 +0100 Message-Id: <20211108152745.1974834-1-michael@amarulasolutions.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Original-Sender: michael@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=F0W8JY0Z; spf=pass (google.com: domain of michael@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=michael@amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , The smm-tlv320aic31xx driver implement audio support of smm-s2-pro BSH system master. Signed-off-by: Michael Trimarchi --- sound/soc/fsl/Kconfig | 11 ++ sound/soc/fsl/Makefile | 2 + sound/soc/fsl/smm-tlv320aic31xx.c | 308 ++++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+) create mode 100644 sound/soc/fsl/smm-tlv320aic31xx.c diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 8e05d092790e..74430bc1e640 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -364,6 +364,17 @@ config SND_SOC_IMX_CARD with OF-graph DT bindings. It also support DPCM of single CPU multi Codec ststem. +config SND_SOC_SMM2_CARD + tristate "SoC Audio Card for SMM2 pro BSH device" + depends on OF && I2C + select SND_SOC_FSL_EASRC + select SND_SOC_TLV320AIC31XX + select SND_SOC_IMX_PCM_DMA + select SND_SOC_FSL_SAI + select SND_SIMPLE_CARD_UTILS + help + This option enables audio sound card support for BSH SMM2 Pro + endif # SND_IMX_SOC endmenu diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index b54beb1a66fa..e85d7f6be709 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -72,6 +72,7 @@ snd-soc-imx-audmix-objs := imx-audmix.o snd-soc-imx-hdmi-objs := imx-hdmi.o snd-soc-imx-rpmsg-objs := imx-rpmsg.o snd-soc-imx-card-objs := imx-card.o +snd-soc-smm-tlv320aic31xx-objs := smm-tlv320aic31xx.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o @@ -81,3 +82,4 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o obj-$(CONFIG_SND_SOC_IMX_CARD) += snd-soc-imx-card.o +obj-$(CONFIG_SND_SOC_SMM2_CARD) += snd-soc-smm-tlv320aic31xx.o diff --git a/sound/soc/fsl/smm-tlv320aic31xx.c b/sound/soc/fsl/smm-tlv320aic31xx.c new file mode 100644 index 000000000000..3aa71031d859 --- /dev/null +++ b/sound/soc/fsl/smm-tlv320aic31xx.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// BSH smm2-pro audio card +// +// Copyright (C) 2021 BSH Hausgeraete GmbH +// +// Author: Michael Trimarchi + +#include +#include +#include +#include +#include +#include +#include + +#include "fsl_sai.h" +#include "../codecs/tlv320aic31xx.h" + +/** + * struct smm_card_priv - Freescale Generic ASOC card private data + * @dai_link: DAI link structure including normal one and DPCM link + * @pdev: platform device pointer + * @card: ASoC card structure + * @sample_rate: Current sample rate + * @sample_format: Current sample format + * @asrc_rate: ASRC sample rate used by Back-Ends + * @asrc_format: ASRC sample format used by Back-Ends + * @dai_fmt: DAI format between CPU and CODEC + * @name: Card name + */ + +struct smm_card_priv { + struct snd_soc_dai_link dai_link[2]; + struct platform_device *pdev; + struct snd_soc_card card; + u32 sample_rate; + snd_pcm_format_t sample_format; + u32 asrc_rate; + snd_pcm_format_t asrc_format; + u32 dai_fmt; + char name[32]; +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /* 1st half -- Normal DAPM routes */ + {"Playback", NULL, "CPU-Playback"}, + /* 2nd half -- ASRC DAPM routes */ + {"CPU-Playback", NULL, "ASRC-Playback"}, +}; + +/* Add all possible widgets into here without being redundant */ +static const struct snd_soc_dapm_widget smm_card_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Ext Spk", NULL), +}; + +static int smm_card_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct smm_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct device *dev = rtd->card->dev; + int ret; + + priv->sample_rate = params_rate(params); + priv->sample_format = params_format(params); + + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 32); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set TDM slot for cpu dai\n"); + goto fail; + } + + ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), AIC31XX_PLL_CLKIN_BCKL, + priv->sample_rate * 256, SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set SYSCLK: %d\n", ret); + goto fail; + } + + return 0; + +fail: + return ret; +} + +static const struct snd_soc_ops smm_card_ops = { + .hw_params = smm_card_hw_params, +}; + +static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct smm_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct snd_interval *rate; + struct snd_mask *mask; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + rate->max = rate->min = priv->asrc_rate; + + mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(mask); + snd_mask_set_format(mask, priv->asrc_format); + + return 0; +} + +SND_SOC_DAILINK_DEFS(hifi_fe, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_be, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +static struct snd_soc_dai_link smm_card_dai[] = { + /* DPCM Link between Front-End and Back-End */ + { + .name = "HiFi-ASRC-FE", + .stream_name = "HiFi-ASRC-FE", + .dpcm_playback = 1, + .dpcm_capture = 0, + .dynamic = 1, + SND_SOC_DAILINK_REG(hifi_fe), + }, + { + .name = "HiFi-ASRC-BE", + .stream_name = "HiFi-ASRC-BE", + .be_hw_params_fixup = be_hw_params_fixup, + .ops = &smm_card_ops, + .dpcm_playback = 1, + .dpcm_capture = 0, + .no_pcm = 1, + SND_SOC_DAILINK_REG(hifi_be), + }, +}; + +static int smm_card_probe(struct platform_device *pdev) +{ + struct device_node *cpu_np, *codec_np, *asrc_np; + struct device_node *np = pdev->dev.of_node; + struct platform_device *asrc_pdev = NULL; + struct platform_device *cpu_pdev; + struct smm_card_priv *priv; + struct device *codec_dev = NULL; + const char *codec_dai_name; + const char *codec_dev_name; + u32 width; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + cpu_np = of_parse_phandle(np, "audio-cpu", 0); + if (!cpu_np) { + dev_err(&pdev->dev, "CPU phandle missing or invalid\n"); + ret = -EINVAL; + goto fail; + } + + cpu_pdev = of_find_device_by_node(cpu_np); + if (!cpu_pdev) { + dev_err(&pdev->dev, "failed to find CPU DAI device\n"); + ret = -EINVAL; + goto fail; + } + + codec_np = of_parse_phandle(np, "audio-codec", 0); + if (codec_np) { + struct platform_device *codec_pdev; + struct i2c_client *codec_i2c; + + codec_i2c = of_find_i2c_device_by_node(codec_np); + if (codec_i2c) { + codec_dev = &codec_i2c->dev; + codec_dev_name = codec_i2c->name; + } + if (!codec_dev) { + codec_pdev = of_find_device_by_node(codec_np); + if (codec_pdev) { + codec_dev = &codec_pdev->dev; + codec_dev_name = codec_pdev->name; + } + } + } + + asrc_np = of_parse_phandle(np, "audio-asrc", 0); + if (asrc_np) + asrc_pdev = of_find_device_by_node(asrc_np); + + if (!asrc_pdev) { + dev_err(&pdev->dev, "Unable to register the ASRC DAI device\n"); + ret = -EINVAL; + goto fail; + } + + /* Default sample rate and format, will be updated in hw_params() */ + priv->sample_rate = 48000; + priv->sample_format = SNDRV_PCM_FORMAT_S32_LE; + priv->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + + memcpy(priv->dai_link, smm_card_dai, + sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); + + codec_dai_name = "tlv320dac31xx-hifi"; + priv->card.dapm_routes = audio_map; + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); + + /* Initialize sound card */ + priv->pdev = pdev; + priv->card.dev = &pdev->dev; + priv->card.owner = THIS_MODULE; + ret = snd_soc_of_parse_card_name(&priv->card, "model"); + if (ret) { + snprintf(priv->name, sizeof(priv->name), "%s-audio", codec_dev_name); + priv->card.name = priv->name; + } + priv->card.dai_link = priv->dai_link; + priv->card.dapm_widgets = smm_card_dapm_widgets; + priv->card.num_dapm_widgets = ARRAY_SIZE(smm_card_dapm_widgets); + + if (of_property_read_bool(np, "audio-routing")) { + ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing"); + if (ret) { + dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret); + goto asrc_fail; + } + } + + /* DPCM DAI Links */ + priv->dai_link[0].cpus->of_node = asrc_np; + priv->dai_link[0].platforms->of_node = asrc_np; + priv->dai_link[1].codecs->dai_name = codec_dai_name; + priv->dai_link[1].codecs->of_node = codec_np; + priv->dai_link[1].cpus->of_node = cpu_np; + priv->dai_link[1].dai_fmt = priv->dai_fmt; + priv->card.num_links = 2; + + ret = of_property_read_u32(asrc_np, "fsl,asrc-rate", + &priv->asrc_rate); + if (ret) { + dev_err(&pdev->dev, "failed to get output rate\n"); + ret = -EINVAL; + goto asrc_fail; + } + + ret = of_property_read_u32(asrc_np, "fsl,asrc-format", + &priv->asrc_format); + if (ret) { + /* Fallback to old binding; translate to asrc_format */ + ret = of_property_read_u32(asrc_np, "fsl,asrc-width", + &width); + if (ret) { + dev_err(&pdev->dev, + "failed to decide output format\n"); + goto asrc_fail; + } + + if (width == 24) + priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + else + priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE; + } + + /* Finish card registering */ + platform_set_drvdata(pdev, priv); + snd_soc_card_set_drvdata(&priv->card, priv); + + ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + goto asrc_fail; + } + +asrc_fail: + of_node_put(asrc_np); + of_node_put(codec_np); + put_device(&cpu_pdev->dev); +fail: + of_node_put(cpu_np); + + return ret; +} + +static const struct of_device_id smm_card_dt_ids[] = { + { .compatible = "bsh,imx-audio-tlv320aic31xx", }, + {} +}; +MODULE_DEVICE_TABLE(of, smm_card_dt_ids); + +static struct platform_driver smm_bsh_card_driver = { + .probe = smm_card_probe, + .driver = { + .name = "smm-tlv320aic31xx", + .pm = &snd_soc_pm_ops, + .of_match_table = smm_card_dt_ids, + }, +}; +module_platform_driver(smm_bsh_card_driver); + +MODULE_DESCRIPTION("BSH smm2-pro audio card"); +MODULE_AUTHOR("Michael Trimarchi "); +MODULE_ALIAS("platform:smm-tlv320aic31xx"); +MODULE_LICENSE("GPL");