// SPDX-License-Identifier: GPL-2.0
/*
 * Greybus Audio Sound SoC helper APIs
 */

#include <linux/debugfs.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include "audio_helper.h"

#define gbaudio_dapm_for_each_direction(dir) \
	for ((dir) = SND_SOC_DAPM_DIR_IN; (dir) <= SND_SOC_DAPM_DIR_OUT; \
		(dir)++)

static void gbaudio_dapm_link_dai_widget(struct snd_soc_dapm_widget *dai_w,
					 struct snd_soc_card *card)
{
	struct snd_soc_dapm_widget *w;
	struct snd_soc_dapm_widget *src, *sink;
	struct snd_soc_dai *dai = dai_w->priv;

	/* ...find all widgets with the same stream and link them */
	list_for_each_entry(w, &card->widgets, list) {
		if (w->dapm != dai_w->dapm)
			continue;

		switch (w->id) {
		case snd_soc_dapm_dai_in:
		case snd_soc_dapm_dai_out:
			continue;
		default:
			break;
		}

		if (!w->sname || !strstr(w->sname, dai_w->sname))
			continue;

		/*
		 * check if widget is already linked,
		 * if (w->linked)
		 *	return;
		 */

		if (dai_w->id == snd_soc_dapm_dai_in) {
			src = dai_w;
			sink = w;
		} else {
			src = w;
			sink = dai_w;
		}
		dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name);
		/* Add the DAPM path and set widget's linked status
		 * snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL);
		 * w->linked = 1;
		 */
	}
}

int gbaudio_dapm_link_component_dai_widgets(struct snd_soc_card *card,
					    struct snd_soc_dapm_context *dapm)
{
	struct snd_soc_dapm_widget *dai_w;

	/* For each DAI widget... */
	list_for_each_entry(dai_w, &card->widgets, list) {
		if (dai_w->dapm != dapm)
			continue;
		switch (dai_w->id) {
		case snd_soc_dapm_dai_in:
		case snd_soc_dapm_dai_out:
			break;
		default:
			continue;
		}
		gbaudio_dapm_link_dai_widget(dai_w, card);
	}

	return 0;
}

static void gbaudio_dapm_free_path(struct snd_soc_dapm_path *path)
{
	list_del(&path->list_node[SND_SOC_DAPM_DIR_IN]);
	list_del(&path->list_node[SND_SOC_DAPM_DIR_OUT]);
	list_del(&path->list_kcontrol);
	list_del(&path->list);
	kfree(path);
}

static void gbaudio_dapm_free_widget(struct snd_soc_dapm_widget *w)
{
	struct snd_soc_dapm_path *p, *next_p;
	enum snd_soc_dapm_direction dir;

	list_del(&w->list);
	/*
	 * remove source and sink paths associated to this widget.
	 * While removing the path, remove reference to it from both
	 * source and sink widgets so that path is removed only once.
	 */
	gbaudio_dapm_for_each_direction(dir) {
		snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p)
			gbaudio_dapm_free_path(p);
	}

	kfree(w->kcontrols);
	kfree_const(w->name);
	kfree_const(w->sname);
	kfree(w);
}

int gbaudio_dapm_free_controls(struct snd_soc_dapm_context *dapm,
			       const struct snd_soc_dapm_widget *widget,
			       int num)
{
	int i;
	struct snd_soc_dapm_widget *w, *next_w;
#ifdef CONFIG_DEBUG_FS
	struct dentry *parent = dapm->debugfs_dapm;
	struct dentry *debugfs_w = NULL;
#endif

	mutex_lock(&dapm->card->dapm_mutex);
	for (i = 0; i < num; i++) {
		/* below logic can be optimized to identify widget pointer */
		list_for_each_entry_safe(w, next_w, &dapm->card->widgets,
					 list) {
			if (w->dapm != dapm)
				continue;
			if (!strcmp(w->name, widget->name))
				break;
			w = NULL;
		}
		if (!w) {
			dev_err(dapm->dev, "%s: widget not found\n",
				widget->name);
			widget++;
			continue;
		}
		widget++;
#ifdef CONFIG_DEBUG_FS
		if (!parent)
			debugfs_w = debugfs_lookup(w->name, parent);
		debugfs_remove(debugfs_w);
		debugfs_w = NULL;
#endif
		gbaudio_dapm_free_widget(w);
	}
	mutex_unlock(&dapm->card->dapm_mutex);
	return 0;
}

static int gbaudio_remove_controls(struct snd_card *card, struct device *dev,
				   const struct snd_kcontrol_new *controls,
				   int num_controls, const char *prefix)
{
	int i, err;

	for (i = 0; i < num_controls; i++) {
		const struct snd_kcontrol_new *control = &controls[i];
		struct snd_ctl_elem_id id;
		struct snd_kcontrol *kctl;

		if (prefix)
			snprintf(id.name, sizeof(id.name), "%s %s", prefix,
				 control->name);
		else
			strscpy(id.name, control->name, sizeof(id.name));
		id.numid = 0;
		id.iface = control->iface;
		id.device = control->device;
		id.subdevice = control->subdevice;
		id.index = control->index;
		kctl = snd_ctl_find_id(card, &id);
		if (!kctl) {
			dev_err(dev, "Failed to find %s\n", control->name);
			continue;
		}
		err = snd_ctl_remove(card, kctl);
		if (err < 0) {
			dev_err(dev, "%d: Failed to remove %s\n", err,
				control->name);
			continue;
		}
	}
	return 0;
}

int gbaudio_remove_component_controls(struct snd_soc_component *component,
				      const struct snd_kcontrol_new *controls,
				      unsigned int num_controls)
{
	struct snd_card *card = component->card->snd_card;

	return gbaudio_remove_controls(card, component->dev, controls,
				       num_controls, component->name_prefix);
}
