diff options
Diffstat (limited to 'sound/soc/intel/boards/sof_maxim_common.c')
| -rw-r--r-- | sound/soc/intel/boards/sof_maxim_common.c | 180 | 
1 files changed, 180 insertions, 0 deletions
| diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index e66dfe666915..112e89951da0 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -5,6 +5,7 @@  #include <linux/string.h>  #include <sound/pcm.h>  #include <sound/soc.h> +#include <sound/soc-acpi.h>  #include <sound/soc-dai.h>  #include <sound/soc-dapm.h>  #include <uapi/sound/asound.h> @@ -134,6 +135,185 @@ void max_98373_set_codec_conf(struct snd_soc_card *card)  EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);  /* + * Maxim MAX98390 + */ +static const struct snd_soc_dapm_route max_98390_dapm_routes[] = { +	/* speaker */ +	{ "Left Spk", NULL, "Left BE_OUT" }, +	{ "Right Spk", NULL, "Right BE_OUT" }, +}; + +static const struct snd_kcontrol_new max_98390_tt_kcontrols[] = { +	SOC_DAPM_PIN_SWITCH("TL Spk"), +	SOC_DAPM_PIN_SWITCH("TR Spk"), +}; + +static const struct snd_soc_dapm_widget max_98390_tt_dapm_widgets[] = { +	SND_SOC_DAPM_SPK("TL Spk", NULL), +	SND_SOC_DAPM_SPK("TR Spk", NULL), +}; + +static const struct snd_soc_dapm_route max_98390_tt_dapm_routes[] = { +	/* Tweeter speaker */ +	{ "TL Spk", NULL, "Tweeter Left BE_OUT" }, +	{ "TR Spk", NULL, "Tweeter Right BE_OUT" }, +}; + +static struct snd_soc_codec_conf max_98390_codec_conf[] = { +	{ +		.dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME), +		.name_prefix = "Right", +	}, +	{ +		.dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME), +		.name_prefix = "Left", +	}, +}; + +static struct snd_soc_codec_conf max_98390_4spk_codec_conf[] = { +	{ +		.dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME), +		.name_prefix = "Right", +	}, +	{ +		.dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME), +		.name_prefix = "Left", +	}, +	{ +		.dlc = COMP_CODEC_CONF(MAX_98390_DEV2_NAME), +		.name_prefix = "Tweeter Right", +	}, +	{ +		.dlc = COMP_CODEC_CONF(MAX_98390_DEV3_NAME), +		.name_prefix = "Tweeter Left", +	}, +}; + +struct snd_soc_dai_link_component max_98390_components[] = { +	{ +		.name = MAX_98390_DEV0_NAME, +		.dai_name = MAX_98390_CODEC_DAI, +	}, +	{ +		.name = MAX_98390_DEV1_NAME, +		.dai_name = MAX_98390_CODEC_DAI, +	}, +}; +EXPORT_SYMBOL_NS(max_98390_components, SND_SOC_INTEL_SOF_MAXIM_COMMON); + +struct snd_soc_dai_link_component max_98390_4spk_components[] = { +	{ +		.name = MAX_98390_DEV0_NAME, +		.dai_name = MAX_98390_CODEC_DAI, +	}, +	{ +		.name = MAX_98390_DEV1_NAME, +		.dai_name = MAX_98390_CODEC_DAI, +	}, +	{ +		.name = MAX_98390_DEV2_NAME, +		.dai_name = MAX_98390_CODEC_DAI, +	}, +	{ +		.name = MAX_98390_DEV3_NAME, +		.dai_name = MAX_98390_CODEC_DAI, +	}, +}; +EXPORT_SYMBOL_NS(max_98390_4spk_components, SND_SOC_INTEL_SOF_MAXIM_COMMON); + +static int max_98390_hw_params(struct snd_pcm_substream *substream, +			       struct snd_pcm_hw_params *params) +{ +	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); +	struct snd_soc_dai *codec_dai; +	int i; + +	for_each_rtd_codec_dais(rtd, i, codec_dai) { +		if (i >= ARRAY_SIZE(max_98390_4spk_components)) { +			dev_err(codec_dai->dev, "invalid codec index %d\n", i); +			return -ENODEV; +		} + +		if (!strcmp(codec_dai->component->name, MAX_98390_DEV0_NAME)) { +			/* DEV0 tdm slot configuration Right */ +			snd_soc_dai_set_tdm_slot(codec_dai, 0x01, 3, 4, 32); +		} +		if (!strcmp(codec_dai->component->name, MAX_98390_DEV1_NAME)) { +			/* DEV1 tdm slot configuration Left */ +			snd_soc_dai_set_tdm_slot(codec_dai, 0x02, 3, 4, 32); +		} + +		if (!strcmp(codec_dai->component->name, MAX_98390_DEV2_NAME)) { +			/* DEVi2 tdm slot configuration Tweeter Right */ +			snd_soc_dai_set_tdm_slot(codec_dai, 0x04, 3, 4, 32); +		} +		if (!strcmp(codec_dai->component->name, MAX_98390_DEV3_NAME)) { +			/* DEV3 tdm slot configuration Tweeter Left */ +			snd_soc_dai_set_tdm_slot(codec_dai, 0x08, 3, 4, 32); +		} +	} +	return 0; +} + +int max_98390_spk_codec_init(struct snd_soc_pcm_runtime *rtd) +{ +	struct snd_soc_card *card = rtd->card; +	int ret; + +	/* add regular speakers dapm route */ +	ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_dapm_routes, +				      ARRAY_SIZE(max_98390_dapm_routes)); +	if (ret) { +		dev_err(rtd->dev, "unable to add Left/Right Speaker dapm, ret %d\n", ret); +		return ret; +	} + +	/* add widgets/controls/dapm for tweeter speakers */ +	if (acpi_dev_present("MX98390", "3", -1)) { +		ret = snd_soc_dapm_new_controls(&card->dapm, max_98390_tt_dapm_widgets, +						ARRAY_SIZE(max_98390_tt_dapm_widgets)); + +		if (ret) { +			dev_err(rtd->dev, "unable to add tweeter dapm controls, ret %d\n", ret); +			/* Don't need to add routes if widget addition failed */ +			return ret; +		} + +		ret = snd_soc_add_card_controls(card, max_98390_tt_kcontrols, +						ARRAY_SIZE(max_98390_tt_kcontrols)); +		if (ret) { +			dev_err(rtd->dev, "unable to add tweeter card controls, ret %d\n", ret); +			return ret; +		} + +		ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_tt_dapm_routes, +					      ARRAY_SIZE(max_98390_tt_dapm_routes)); +		if (ret) +			dev_err(rtd->dev, +				"unable to add Tweeter Left/Right Speaker dapm, ret %d\n", ret); +	} +	return ret; +} +EXPORT_SYMBOL_NS(max_98390_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON); + +const struct snd_soc_ops max_98390_ops = { +	.hw_params = max_98390_hw_params, +}; +EXPORT_SYMBOL_NS(max_98390_ops, SND_SOC_INTEL_SOF_MAXIM_COMMON); + +void max_98390_set_codec_conf(struct snd_soc_card *card, int ch) +{ +	if (ch == ARRAY_SIZE(max_98390_4spk_codec_conf)) { +		card->codec_conf = max_98390_4spk_codec_conf; +		card->num_configs = ARRAY_SIZE(max_98390_4spk_codec_conf); +	} else { +		card->codec_conf = max_98390_codec_conf; +		card->num_configs = ARRAY_SIZE(max_98390_codec_conf); +	} +} +EXPORT_SYMBOL_NS(max_98390_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON); + +/*   * Maxim MAX98357A/MAX98360A   */  static const struct snd_kcontrol_new max_98357a_kcontrols[] = { |