162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// This file is provided under a dual BSD/GPLv2 license.  When using or
462306a36Sopenharmony_ci// redistributing this file, you may do so under either license.
562306a36Sopenharmony_ci//
662306a36Sopenharmony_ci// Copyright(c) 2018 Intel Corporation. All rights reserved.
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
962306a36Sopenharmony_ci//
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <sound/sof.h>
1362306a36Sopenharmony_ci#include "sof-audio.h"
1462306a36Sopenharmony_ci#include "sof-priv.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic struct snd_soc_card sof_nocodec_card = {
1762306a36Sopenharmony_ci	.name = "nocodec", /* the sof- prefix is added by the core */
1862306a36Sopenharmony_ci	.topology_shortname = "sof-nocodec",
1962306a36Sopenharmony_ci	.owner = THIS_MODULE
2062306a36Sopenharmony_ci};
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic int sof_nocodec_bes_setup(struct device *dev,
2362306a36Sopenharmony_ci				 struct snd_soc_dai_driver *drv,
2462306a36Sopenharmony_ci				 struct snd_soc_dai_link *links,
2562306a36Sopenharmony_ci				 int link_num, struct snd_soc_card *card)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	struct snd_soc_dai_link_component *dlc;
2862306a36Sopenharmony_ci	int i;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	if (!drv || !links || !card)
3162306a36Sopenharmony_ci		return -EINVAL;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	/* set up BE dai_links */
3462306a36Sopenharmony_ci	for (i = 0; i < link_num; i++) {
3562306a36Sopenharmony_ci		dlc = devm_kcalloc(dev, 2, sizeof(*dlc), GFP_KERNEL);
3662306a36Sopenharmony_ci		if (!dlc)
3762306a36Sopenharmony_ci			return -ENOMEM;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci		links[i].name = devm_kasprintf(dev, GFP_KERNEL,
4062306a36Sopenharmony_ci					       "NoCodec-%d", i);
4162306a36Sopenharmony_ci		if (!links[i].name)
4262306a36Sopenharmony_ci			return -ENOMEM;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		links[i].stream_name = links[i].name;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci		links[i].cpus = &dlc[0];
4762306a36Sopenharmony_ci		links[i].codecs = &asoc_dummy_dlc;
4862306a36Sopenharmony_ci		links[i].platforms = &dlc[1];
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci		links[i].num_cpus = 1;
5162306a36Sopenharmony_ci		links[i].num_codecs = 1;
5262306a36Sopenharmony_ci		links[i].num_platforms = 1;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci		links[i].id = i;
5562306a36Sopenharmony_ci		links[i].no_pcm = 1;
5662306a36Sopenharmony_ci		links[i].cpus->dai_name = drv[i].name;
5762306a36Sopenharmony_ci		links[i].platforms->name = dev_name(dev->parent);
5862306a36Sopenharmony_ci		if (drv[i].playback.channels_min)
5962306a36Sopenharmony_ci			links[i].dpcm_playback = 1;
6062306a36Sopenharmony_ci		if (drv[i].capture.channels_min)
6162306a36Sopenharmony_ci			links[i].dpcm_capture = 1;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci		links[i].be_hw_params_fixup = sof_pcm_dai_link_fixup;
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	card->dai_link = links;
6762306a36Sopenharmony_ci	card->num_links = link_num;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return 0;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic int sof_nocodec_setup(struct device *dev,
7362306a36Sopenharmony_ci			     u32 num_dai_drivers,
7462306a36Sopenharmony_ci			     struct snd_soc_dai_driver *dai_drivers)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	struct snd_soc_dai_link *links;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	/* create dummy BE dai_links */
7962306a36Sopenharmony_ci	links = devm_kcalloc(dev, num_dai_drivers, sizeof(struct snd_soc_dai_link), GFP_KERNEL);
8062306a36Sopenharmony_ci	if (!links)
8162306a36Sopenharmony_ci		return -ENOMEM;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	return sof_nocodec_bes_setup(dev, dai_drivers, links, num_dai_drivers, &sof_nocodec_card);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic int sof_nocodec_probe(struct platform_device *pdev)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	struct snd_soc_card *card = &sof_nocodec_card;
8962306a36Sopenharmony_ci	struct snd_soc_acpi_mach *mach;
9062306a36Sopenharmony_ci	int ret;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	card->dev = &pdev->dev;
9362306a36Sopenharmony_ci	card->topology_shortname_created = true;
9462306a36Sopenharmony_ci	mach = pdev->dev.platform_data;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	ret = sof_nocodec_setup(card->dev, mach->mach_params.num_dai_drivers,
9762306a36Sopenharmony_ci				mach->mach_params.dai_drivers);
9862306a36Sopenharmony_ci	if (ret < 0)
9962306a36Sopenharmony_ci		return ret;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	return devm_snd_soc_register_card(&pdev->dev, card);
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic struct platform_driver sof_nocodec_audio = {
10562306a36Sopenharmony_ci	.probe = sof_nocodec_probe,
10662306a36Sopenharmony_ci	.driver = {
10762306a36Sopenharmony_ci		.name = "sof-nocodec",
10862306a36Sopenharmony_ci		.pm = &snd_soc_pm_ops,
10962306a36Sopenharmony_ci	},
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_cimodule_platform_driver(sof_nocodec_audio)
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC sof nocodec");
11462306a36Sopenharmony_ciMODULE_AUTHOR("Liam Girdwood");
11562306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
11662306a36Sopenharmony_ciMODULE_ALIAS("platform:sof-nocodec");
117