From patchwork Mon Nov 8 13:57:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Trimarchi X-Patchwork-Id: 1729 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id C1ADE3F159 for ; Mon, 8 Nov 2021 14:57:54 +0100 (CET) Received: by mail-wm1-f72.google.com with SMTP id k25-20020a05600c1c9900b00332f798ba1dsf10185357wms.4 for ; Mon, 08 Nov 2021 05:57:54 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1636379874; cv=pass; d=google.com; s=arc-20160816; b=t95OSp4hh5A/LTeZYcX+tai8dHe/w5DGAAQ0QZ0DzctDliRDUSVJ69qU4QSlJks2Jf ZkxwdIK340qci5Iu0r/e62Hv9Mu/zV/zhkal6e8BYbo5u9+hRiE5U3cV0iCkObT8josr S+aAUQxEDzcJfcSM0PMsWkCx1G0+DCz/zEscZ7xhR8cK9YOQmFereB8qi6Cfrdmce8So c+CIJAuKVhVBCeK52QhnomB4V9n7Pag6EK5gk12FnVP+OIhDC+sAA+5XP5bA7RanAm8i JRkZtuuYHh9+t1V/0p5KSJt9uch8EpY6AbM3DJXBYw+NyCB7Y7pn4lGtxnzzQZmKEJTG mkFg== 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=SV1ebr2lXKG4pHhbYBjWfJIu915O0QDTtW1jqEOUYbM=; b=vByHI+JYBtyLcjqgYoDb4dVjkbQ2GxxsZR+qd//PW3Ukyhev8WebmqB0kX59XOepLo yz1FkhPce3CGjwzrS8ekYbkvIsyHzi/h7FixuAU6yuiuHcEi38ScrIxskUcGkxKwOgnM /Ge4G7ew+gEmgXiyv7lH+NWx7dBiXsmfP4IagU14Q8qwWRioYRcAiRDfz9PLJxPBJng4 dTErwR74YiKRu0VMiMrmHxTcSOsVCd05vWn5P+u4ZoDWSKulh3sHP0wslJCMMYAqfgaA Su+P/XbEvP5AnKmUqaDCWOhWNoq8LSRW4ZeYC2MHAY7X12ptp/bX+RmswrZwlqLMwKbW QKbw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=LTv3rheX; 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=SV1ebr2lXKG4pHhbYBjWfJIu915O0QDTtW1jqEOUYbM=; b=eZ2P/sEyNm7V/T8Ct3u7z8+ROOmFlFUfVX7D6xYbVeuvT3hOr8lolAOdNPCf6gDjQz AI81Ec+oyNP2uU8IHHZQChoS+mrXOkRQDPrue072VqI9hoWa3u3GW0/erV+iMvntXDQ2 /T56MpLMWpZxM8RKnVixzaD16H++Gd9U5mLFA= 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=SV1ebr2lXKG4pHhbYBjWfJIu915O0QDTtW1jqEOUYbM=; b=7ttMmuhRMeNC5s3iJaAKG6iA6i0LXrnWZFdWk/ke5f4eCPFnOprwKOHmN5Cp0trM+D S7iwxZn0xZKVeVvkt8MMx+KZZkRNNHO2y9vnRZVr+eGxyJd7S2DZwIfxNyIT2U0ZdhrK cM1+V2hYcQE+LgxQO9iOK5rk6qsf1e2dVf5xhhziDbHuz3y8Ep8iV28s1PKmp4aKImJ6 MGcpRjedaL0oEm6JWJwpF7kO6wRpNw+xT21VCJpc3tusP7WMDTHRRWELeHh9wQKRC93I k/gpFgYQH3QkkH08sOAYxI1OVqV5PGJBwXkAPySynKCdnzkDhWg1NTafT6zsbNgtYA85 ROqw== X-Gm-Message-State: AOAM530DBnjNyaujsCwoYjz/gi/iVELOvpnZYGjrEBMNJ+64JemkITNp 1WJp0v3buyPOWqDztk5OD8vKD4IW X-Google-Smtp-Source: ABdhPJz0Q0Ns+vX1TD4ssaaQsIQU9dCqjpdJDCV1maNNNDoLLhKJXGA1J/ZnlZ295xFCEpBsdzecIA== X-Received: by 2002:a05:600c:6d2:: with SMTP id b18mr54930330wmn.98.1636379874359; Mon, 08 Nov 2021 05:57:54 -0800 (PST) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a1c:23c8:: with SMTP id j191ls3340276wmj.1.gmail; Mon, 08 Nov 2021 05:57:53 -0800 (PST) X-Received: by 2002:a7b:cd96:: with SMTP id y22mr42280644wmj.121.1636379873270; Mon, 08 Nov 2021 05:57:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1636379873; cv=none; d=google.com; s=arc-20160816; b=Ie/tzv0mBrLXNigYdX/umKGzfIiHI7fiJJst1TOpC8dlTuelglo8wc3anYEoV7n2jY 2OwIav/zlcz6GVqHYht6HyVEd5LKbvujZxKy50NwA7y0MduclH4b2f3oN9q9dt4hgHYp hR5qHPazXeILcCgAHzCtSdedIi17RFAwnMkkYggpTyns6J7uf9LzCnOlKstJGUDb2o8P Dxt3RNfo2qF8Kp3kEAvKsAqsojOmnGWQgqYpvn6VajHrevQ3hF2U9hKcrK9h0MWNP8EC t9THb5lLt3K3J33DjIYlqsmgOHQbL/PJCC5u58v+nSfUlUhGrq+qNigGZNMWN3eZ3W+v 1rdg== 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=F14HoUTHO3yeEn4oJ8wOqqLe6X1VVIoNpUFo9lk0Gtc=; b=c6q0YO6o6k4hUFh2EoA9N3bRcDv6C0oGc0EcBS4GOwolIJZnZPFhm9+kNh17Miksoj Sllj4pZW37aNr56T4EFHbI+5qTJyqi8liY/Ibd8Vl5nFFwhl2dxAzv2Mr7tNM2r8v7AQ PFwHBJsLE+GQh3eiIlBR07fZ8TtUptod3qsDyuDtNFoZi63stq68VI4Kz8E0+0vnurOw QltZJWlRDntaAz34viqJtzdWdjHkB9BKofs4nV+eoh2g7vv1F/QUASXtoBKqdJP6yZs8 F8i5UrGkAwPj0skdV2kIhSKewk/97lXXzoA3bspjwMPngyH9qKdH1XmQLW0ZaQUv37lz F0Xg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=LTv3rheX; 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 w4sor9241412wmc.0.2021.11.08.05.57.53 for (Google Transport Security); Mon, 08 Nov 2021 05:57:53 -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:a05:600c:4ed2:: with SMTP id g18mr32624078wmq.122.1636379872825; Mon, 08 Nov 2021 05:57:52 -0800 (PST) Received: from panicking.amarulasolutions.com ([2.198.173.211]) by smtp.gmail.com with ESMTPSA id l5sm19691818wms.16.2021.11.08.05.57.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Nov 2021 05:57:52 -0800 (PST) From: Michael Trimarchi To: Ariel D'Alessandro Cc: linux-amarula@amarulasolutions.com, Anthony Brandon Subject: [PATCH 1/3] ASoC: fsl: add smm-s2-pro audio driver Date: Mon, 8 Nov 2021 14:57:48 +0100 Message-Id: <20211108135750.1931056-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=LTv3rheX; 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 | 315 ++++++++++++++++++++++++++++++ 3 files changed, 328 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..4666c6b04173 --- /dev/null +++ b/sound/soc/fsl/smm-tlv320aic31xx.c @@ -0,0 +1,315 @@ +// 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 fsl_asoc_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 fsl_asoc_card_ops = { + .hw_params = fsl_asoc_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, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +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 fsl_asoc_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 = &fsl_asoc_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 device_node *bitclkprovider = NULL; + struct device_node *frameprovider = 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, fsl_asoc_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");