File Index
Files and directories
Sign in
FILE

pcm3168a.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/intel/avs/boards/pcm3168a.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2//
  3// Copyright(c) 2024-2025 Intel Corporation
  4//
  5// Author: Cezary Rojewski <cezary.rojewski@intel.com>
  6//
  7
  8#include <linux/module.h>
  9#include <linux/platform_device.h>
 10#include <sound/core.h>
 11#include <sound/pcm.h>
 12#include <sound/pcm_params.h>
 13#include <sound/soc.h>
 14#include <sound/soc-acpi.h>
 15#include "../utils.h"
 16
 17static const struct snd_soc_dapm_widget card_widgets[] = {
 18	SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL),
 19	SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL),
 20	SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL),
 21	SND_SOC_DAPM_LINE("CPB Line Out", NULL),
 22	SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL),
 23	SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL),
 24	SND_SOC_DAPM_LINE("CPB Line In", NULL),
 25};
 26
 27static const struct snd_soc_dapm_route card_routes[] = {
 28	{ "CPB Stereo HP 1", NULL, "AOUT1L" },
 29	{ "CPB Stereo HP 1", NULL, "AOUT1R" },
 30	{ "CPB Stereo HP 2", NULL, "AOUT2L" },
 31	{ "CPB Stereo HP 2", NULL, "AOUT2R" },
 32	{ "CPB Stereo HP 3", NULL, "AOUT3L" },
 33	{ "CPB Stereo HP 3", NULL, "AOUT3R" },
 34	{ "CPB Line Out", NULL, "AOUT4L" },
 35	{ "CPB Line Out", NULL, "AOUT4R" },
 36
 37	{ "AIN1L", NULL, "CPB Stereo Mic 1" },
 38	{ "AIN1R", NULL, "CPB Stereo Mic 1" },
 39	{ "AIN2L", NULL, "CPB Stereo Mic 2" },
 40	{ "AIN2R", NULL, "CPB Stereo Mic 2" },
 41	{ "AIN3L", NULL, "CPB Line In" },
 42	{ "AIN3R", NULL, "CPB Line In" },
 43};
 44
 45static int avs_pcm3168a_be_fixup(struct snd_soc_pcm_runtime *runtime,
 46				 struct snd_pcm_hw_params *params)
 47{
 48	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 49
 50	/* Set SSP to 24 bit. */
 51	snd_mask_none(fmt);
 52	snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
 53
 54	return 0;
 55}
 56
 57SND_SOC_DAILINK_DEF(pcm3168a_dac,
 58		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-PCM3168A:00", "pcm3168a-dac")));
 59SND_SOC_DAILINK_DEF(pcm3168a_adc,
 60		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-PCM3168A:00", "pcm3168a-adc")));
 61SND_SOC_DAILINK_DEF(cpu_ssp0, DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
 62SND_SOC_DAILINK_DEF(cpu_ssp2, DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin")));
 63
 64static int avs_create_dai_links(struct device *dev, struct snd_soc_dai_link **links, int *num_links)
 65{
 66	struct snd_soc_dai_link_component *platform;
 67	struct snd_soc_dai_link *dl;
 68	const int num_dl = 2;
 69
 70	dl = devm_kcalloc(dev, num_dl, sizeof(*dl), GFP_KERNEL);
 71	platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL);
 72	if (!dl || !platform)
 73		return -ENOMEM;
 74
 75	platform->name = dev_name(dev);
 76	dl[0].num_cpus = 1;
 77	dl[0].num_codecs = 1;
 78	dl[0].platforms = platform;
 79	dl[0].num_platforms = 1;
 80	dl[0].dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
 81	dl[0].be_hw_params_fixup = avs_pcm3168a_be_fixup;
 82	dl[0].nonatomic = 1;
 83	dl[0].no_pcm = 1;
 84	memcpy(&dl[1], &dl[0], sizeof(*dl));
 85
 86	dl[0].name = "SSP0-Codec-dac";
 87	dl[0].cpus = cpu_ssp0;
 88	dl[0].codecs = pcm3168a_dac;
 89	dl[1].name = "SSP2-Codec-adc";
 90	dl[1].cpus = cpu_ssp2;
 91	dl[1].codecs = pcm3168a_adc;
 92
 93	*links = dl;
 94	*num_links = num_dl;
 95	return 0;
 96}
 97
 98static int avs_pcm3168a_probe(struct platform_device *pdev)
 99{
100	struct snd_soc_acpi_mach *mach;
101	struct avs_mach_pdata *pdata;
102	struct device *dev = &pdev->dev;
103	struct snd_soc_card *card;
104	int ret;
105
106	mach = dev_get_platdata(dev);
107	pdata = mach->pdata;
108
109	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
110	if (!card)
111		return -ENOMEM;
112
113	ret = avs_create_dai_links(dev, &card->dai_link, &card->num_links);
114	if (ret)
115		return ret;
116
117	if (pdata->obsolete_card_names) {
118		card->name = "avs_pcm3168a";
119	} else {
120		card->driver_name = "avs_pcm3168a";
121		card->long_name = card->name = "AVS I2S PCM3168A";
122	}
123	card->dev = dev;
124	card->owner = THIS_MODULE;
125	card->dapm_widgets = card_widgets;
126	card->num_dapm_widgets = ARRAY_SIZE(card_widgets);
127	card->dapm_routes = card_routes;
128	card->num_dapm_routes = ARRAY_SIZE(card_routes);
129	card->fully_routed = true;
130
131	return devm_snd_soc_register_deferrable_card(dev, card);
132}
133
134static const struct platform_device_id avs_pcm3168a_driver_ids[] = {
135	{
136		.name = "avs_pcm3168a",
137	},
138	{},
139};
140MODULE_DEVICE_TABLE(platform, avs_pcm3168a_driver_ids);
141
142static struct platform_driver avs_pcm3168a_driver = {
143	.probe = avs_pcm3168a_probe,
144	.driver = {
145		.name = "avs_pcm3168a",
146		.pm = &snd_soc_pm_ops,
147	},
148	.id_table = avs_pcm3168a_driver_ids,
149};
150
151module_platform_driver(avs_pcm3168a_driver);
152
153MODULE_DESCRIPTION("Intel pcm3168a machine driver");
154MODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>");
155MODULE_LICENSE("GPL");
~/ Read-only file preview.