Path: blob/master/sound/soc/intel/avs/boards/max98357a.c
26607 views
// SPDX-License-Identifier: GPL-2.0-only1//2// Copyright(c) 2021-2022 Intel Corporation3//4// Authors: Cezary Rojewski <[email protected]>5// Amadeusz Slawinski <[email protected]>6//78#include <linux/module.h>9#include <linux/platform_device.h>10#include <sound/pcm_params.h>11#include <sound/soc.h>12#include <sound/soc-acpi.h>13#include <sound/soc-dapm.h>14#include "../utils.h"1516static const struct snd_kcontrol_new card_controls[] = {17SOC_DAPM_PIN_SWITCH("Spk"),18};1920static const struct snd_soc_dapm_widget card_widgets[] = {21SND_SOC_DAPM_SPK("Spk", NULL),22};2324static const struct snd_soc_dapm_route card_base_routes[] = {25{ "Spk", NULL, "Speaker" },26};2728static int29avs_max98357a_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params)30{31struct snd_interval *rate, *channels;32struct snd_mask *fmt;3334rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);35channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);36fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);3738/* The ADSP will convert the FE rate to 48k, stereo */39rate->min = rate->max = 48000;40channels->min = channels->max = 2;4142/* set SSP0 to 16 bit */43snd_mask_none(fmt);44snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);45return 0;46}4748static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,49int tdm_slot, struct snd_soc_dai_link **dai_link)50{51struct snd_soc_dai_link_component *platform;52struct snd_soc_dai_link *dl;5354dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL);55platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL);56if (!dl || !platform)57return -ENOMEM;5859platform->name = platform_name;6061dl->name = devm_kasprintf(dev, GFP_KERNEL,62AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot));63dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL);64dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL);65if (!dl->name || !dl->cpus || !dl->codecs)66return -ENOMEM;6768dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,69AVS_STRING_FMT("SSP", " Pin", ssp_port, tdm_slot));70dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "MX98357A:00");71dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "HiFi");72if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name)73return -ENOMEM;7475dl->num_cpus = 1;76dl->num_codecs = 1;77dl->platforms = platform;78dl->num_platforms = 1;79dl->id = 0;80dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;81dl->be_hw_params_fixup = avs_max98357a_be_fixup;82dl->nonatomic = 1;83dl->no_pcm = 1;84dl->playback_only = 1;8586*dai_link = dl;8788return 0;89}9091static int avs_max98357a_probe(struct platform_device *pdev)92{93struct snd_soc_dai_link *dai_link;94struct snd_soc_acpi_mach *mach;95struct avs_mach_pdata *pdata;96struct snd_soc_card *card;97struct device *dev = &pdev->dev;98const char *pname;99int ssp_port, tdm_slot, ret;100101mach = dev_get_platdata(dev);102pname = mach->mach_params.platform;103pdata = mach->pdata;104105ret = avs_mach_get_ssp_tdm(dev, mach, &ssp_port, &tdm_slot);106if (ret)107return ret;108109ret = avs_create_dai_link(dev, pname, ssp_port, tdm_slot, &dai_link);110if (ret) {111dev_err(dev, "Failed to create dai link: %d", ret);112return ret;113}114115card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);116if (!card)117return -ENOMEM;118119if (pdata->obsolete_card_names) {120card->name = "avs_max98357a";121} else {122card->driver_name = "avs_max98357a";123card->long_name = card->name = "AVS I2S MAX98357A";124}125card->dev = dev;126card->owner = THIS_MODULE;127card->dai_link = dai_link;128card->num_links = 1;129card->controls = card_controls;130card->num_controls = ARRAY_SIZE(card_controls);131card->dapm_widgets = card_widgets;132card->num_dapm_widgets = ARRAY_SIZE(card_widgets);133card->dapm_routes = card_base_routes;134card->num_dapm_routes = ARRAY_SIZE(card_base_routes);135card->fully_routed = true;136137ret = snd_soc_fixup_dai_links_platform_name(card, pname);138if (ret)139return ret;140141return devm_snd_soc_register_deferrable_card(dev, card);142}143144static const struct platform_device_id avs_max98357a_driver_ids[] = {145{146.name = "avs_max98357a",147},148{},149};150MODULE_DEVICE_TABLE(platform, avs_max98357a_driver_ids);151152static struct platform_driver avs_max98357a_driver = {153.probe = avs_max98357a_probe,154.driver = {155.name = "avs_max98357a",156.pm = &snd_soc_pm_ops,157},158.id_table = avs_max98357a_driver_ids,159};160161module_platform_driver(avs_max98357a_driver)162163MODULE_DESCRIPTION("Intel max98357a machine driver");164MODULE_LICENSE("GPL");165166167