Skip to content

Commit

Permalink
ASoC: sdw_utils/intel: move soundwire endpoint parsing helper functions
Browse files Browse the repository at this point in the history
Move SoundWire endpoint parsing helper functions to common place holder.
These functions will be used by other platform machine driver code.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
  • Loading branch information
vijendarmukunda committed Sep 10, 2024
1 parent bfbc3c5 commit 31f30fb
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 158 deletions.
10 changes: 10 additions & 0 deletions include/sound/soc_sdw_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,16 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
int (*init)(struct snd_soc_pcm_runtime *rtd),
const struct snd_soc_ops *ops);

int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends);

struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
const struct snd_soc_acpi_endpoint *new);

int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
struct asoc_sdw_dailink *soc_dais,
struct asoc_sdw_endpoint *soc_ends,
int *num_devs);

int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd);

/* DMIC support */
Expand Down
158 changes: 0 additions & 158 deletions sound/soc/intel/boards/sof_sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,164 +638,6 @@ static const struct snd_soc_ops sdw_ops = {

static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};

static int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends)
{
struct device *dev = card->dev;
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
const struct snd_soc_acpi_link_adr *adr_link;
int i;

for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
*num_devs += adr_link->num_adr;

for (i = 0; i < adr_link->num_adr; i++)
*num_ends += adr_link->adr_d[i].num_endpoints;
}

dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends);

return 0;
}

static struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
const struct snd_soc_acpi_endpoint *new)
{
while (dailinks->initialised) {
if (new->aggregated && dailinks->group_id == new->group_id)
return dailinks;

dailinks++;
}

INIT_LIST_HEAD(&dailinks->endpoints);
dailinks->group_id = new->group_id;
dailinks->initialised = true;

return dailinks;
}

static int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
struct asoc_sdw_dailink *sof_dais,
struct asoc_sdw_endpoint *sof_ends,
int *num_devs)
{
struct device *dev = card->dev;
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
const struct snd_soc_acpi_link_adr *adr_link;
struct asoc_sdw_endpoint *sof_end = sof_ends;
int num_dais = 0;
int i, j;
int ret;

for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
int num_link_dailinks = 0;

if (!is_power_of_2(adr_link->mask)) {
dev_err(dev, "link with multiple mask bits: 0x%x\n",
adr_link->mask);
return -EINVAL;
}

for (i = 0; i < adr_link->num_adr; i++) {
const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
struct asoc_sdw_codec_info *codec_info;
const char *codec_name;

if (!adr_dev->name_prefix) {
dev_err(dev, "codec 0x%llx does not have a name prefix\n",
adr_dev->adr);
return -EINVAL;
}

codec_info = asoc_sdw_find_codec_info_part(adr_dev->adr);
if (!codec_info)
return -EINVAL;

ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic;

codec_name = asoc_sdw_get_codec_name(dev, codec_info, adr_link, i);
if (!codec_name)
return -ENOMEM;

dev_dbg(dev, "Adding prefix %s for %s\n",
adr_dev->name_prefix, codec_name);

sof_end->name_prefix = adr_dev->name_prefix;

if (codec_info->count_sidecar && codec_info->add_sidecar) {
ret = codec_info->count_sidecar(card, &num_dais, num_devs);
if (ret)
return ret;

sof_end->include_sidecar = true;
}

for (j = 0; j < adr_dev->num_endpoints; j++) {
const struct snd_soc_acpi_endpoint *adr_end;
const struct asoc_sdw_dai_info *dai_info;
struct asoc_sdw_dailink *sof_dai;
int stream;

adr_end = &adr_dev->endpoints[j];
dai_info = &codec_info->dais[adr_end->num];
sof_dai = asoc_sdw_find_dailink(sof_dais, adr_end);

if (dai_info->quirk && !(dai_info->quirk & sof_sdw_quirk))
continue;

dev_dbg(dev,
"Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n",
ffs(adr_link->mask) - 1, adr_dev->adr,
adr_end->num, type_strings[dai_info->dai_type],
dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-',
dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-',
adr_end->aggregated ? "group" : "solo",
adr_end->group_id);

if (adr_end->num >= codec_info->dai_num) {
dev_err(dev,
"%d is too many endpoints for codec: 0x%x\n",
adr_end->num, codec_info->part_id);
return -EINVAL;
}

for_each_pcm_streams(stream) {
if (dai_info->direction[stream] &&
dai_info->dailink[stream] < 0) {
dev_err(dev,
"Invalid dailink id %d for codec: 0x%x\n",
dai_info->dailink[stream],
codec_info->part_id);
return -EINVAL;
}

if (dai_info->direction[stream]) {
num_dais += !sof_dai->num_devs[stream];
sof_dai->num_devs[stream]++;
sof_dai->link_mask[stream] |= adr_link->mask;
}
}

num_link_dailinks += !!list_empty(&sof_dai->endpoints);
list_add_tail(&sof_end->list, &sof_dai->endpoints);

sof_end->link_mask = adr_link->mask;
sof_end->codec_name = codec_name;
sof_end->codec_info = codec_info;
sof_end->dai_info = dai_info;
sof_end++;
}
}

ctx->append_dai_type |= (num_link_dailinks > 1);
}

return num_dais;
}

static int create_sdw_dailink(struct snd_soc_card *card,
struct asoc_sdw_dailink *sof_dai,
struct snd_soc_dai_link **dai_links,
Expand Down
163 changes: 163 additions & 0 deletions sound/soc/sdw_utils/soc_sdw_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1005,5 +1005,168 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
}
EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, SND_SOC_SDW_UTILS);

int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends)
{
struct device *dev = card->dev;
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
const struct snd_soc_acpi_link_adr *adr_link;
int i;

for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
*num_devs += adr_link->num_adr;

for (i = 0; i < adr_link->num_adr; i++)
*num_ends += adr_link->adr_d[i].num_endpoints;
}

dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends);

return 0;
}
EXPORT_SYMBOL_NS(asoc_sdw_count_sdw_endpoints, SND_SOC_SDW_UTILS);

struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
const struct snd_soc_acpi_endpoint *new)
{
while (dailinks->initialised) {
if (new->aggregated && dailinks->group_id == new->group_id)
return dailinks;

dailinks++;
}

INIT_LIST_HEAD(&dailinks->endpoints);
dailinks->group_id = new->group_id;
dailinks->initialised = true;

return dailinks;
}
EXPORT_SYMBOL_NS(asoc_sdw_find_dailink, SND_SOC_SDW_UTILS);

static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};

int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
struct asoc_sdw_dailink *soc_dais,
struct asoc_sdw_endpoint *soc_ends,
int *num_devs)
{
struct device *dev = card->dev;
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
const struct snd_soc_acpi_link_adr *adr_link;
struct asoc_sdw_endpoint *soc_end = soc_ends;
int num_dais = 0;
int i, j;
int ret;

for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
int num_link_dailinks = 0;

if (!is_power_of_2(adr_link->mask)) {
dev_err(dev, "link with multiple mask bits: 0x%x\n",
adr_link->mask);
return -EINVAL;
}

for (i = 0; i < adr_link->num_adr; i++) {
const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i];
struct asoc_sdw_codec_info *codec_info;
const char *codec_name;

if (!adr_dev->name_prefix) {
dev_err(dev, "codec 0x%llx does not have a name prefix\n",
adr_dev->adr);
return -EINVAL;
}

codec_info = asoc_sdw_find_codec_info_part(adr_dev->adr);
if (!codec_info)
return -EINVAL;

ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic;

codec_name = asoc_sdw_get_codec_name(dev, codec_info, adr_link, i);
if (!codec_name)
return -ENOMEM;

dev_dbg(dev, "Adding prefix %s for %s\n",
adr_dev->name_prefix, codec_name);

soc_end->name_prefix = adr_dev->name_prefix;

if (codec_info->count_sidecar && codec_info->add_sidecar) {
ret = codec_info->count_sidecar(card, &num_dais, num_devs);
if (ret)
return ret;

soc_end->include_sidecar = true;
}

for (j = 0; j < adr_dev->num_endpoints; j++) {
const struct snd_soc_acpi_endpoint *adr_end;
const struct asoc_sdw_dai_info *dai_info;
struct asoc_sdw_dailink *soc_dai;
int stream;

adr_end = &adr_dev->endpoints[j];
dai_info = &codec_info->dais[adr_end->num];
soc_dai = asoc_sdw_find_dailink(soc_dais, adr_end);

if (dai_info->quirk && !(dai_info->quirk & ctx->mc_quirk))
continue;

dev_dbg(dev,
"Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n",
ffs(adr_link->mask) - 1, adr_dev->adr,
adr_end->num, type_strings[dai_info->dai_type],
dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-',
dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-',
adr_end->aggregated ? "group" : "solo",
adr_end->group_id);

if (adr_end->num >= codec_info->dai_num) {
dev_err(dev,
"%d is too many endpoints for codec: 0x%x\n",
adr_end->num, codec_info->part_id);
return -EINVAL;
}

for_each_pcm_streams(stream) {
if (dai_info->direction[stream] &&
dai_info->dailink[stream] < 0) {
dev_err(dev,
"Invalid dailink id %d for codec: 0x%x\n",
dai_info->dailink[stream],
codec_info->part_id);
return -EINVAL;
}

if (dai_info->direction[stream]) {
num_dais += !soc_dai->num_devs[stream];
soc_dai->num_devs[stream]++;
soc_dai->link_mask[stream] |= adr_link->mask;
}
}

num_link_dailinks += !!list_empty(&soc_dai->endpoints);
list_add_tail(&soc_end->list, &soc_dai->endpoints);

soc_end->link_mask = adr_link->mask;
soc_end->codec_name = codec_name;
soc_end->codec_info = codec_info;
soc_end->dai_info = dai_info;
soc_end++;
}
}

ctx->append_dai_type |= (num_link_dailinks > 1);
}

return num_dais;
}
EXPORT_SYMBOL_NS(asoc_sdw_parse_sdw_endpoints, SND_SOC_SDW_UTILS);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SoundWire ASoC helpers");

0 comments on commit 31f30fb

Please sign in to comment.