diff options
Diffstat (limited to 'sound/soc/intel/boards/sof_maxim_common.c')
| -rw-r--r-- | sound/soc/intel/boards/sof_maxim_common.c | 170 | 
1 files changed, 100 insertions, 70 deletions
diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 112e89951da0..628b6d5d3ee4 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -4,6 +4,7 @@  #include <linux/module.h>  #include <linux/string.h>  #include <sound/pcm.h> +#include <sound/pcm_params.h>  #include <sound/soc.h>  #include <sound/soc-acpi.h>  #include <sound/soc-dai.h> @@ -11,6 +12,18 @@  #include <uapi/sound/asound.h>  #include "sof_maxim_common.h" +/* helper function to get the number of specific codec */ +static unsigned int get_num_codecs(const char *hid) +{ +	struct acpi_device *adev; +	unsigned int dev_num = 0; + +	for_each_acpi_dev_match(adev, hid, NULL, -1) +		dev_num++; + +	return dev_num; +} +  #define MAX_98373_PIN_NAME 16  const struct snd_soc_dapm_route max_98373_dapm_routes[] = { @@ -168,17 +181,6 @@ static struct snd_soc_codec_conf max_98390_codec_conf[] = {  		.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", @@ -189,19 +191,7 @@ static struct snd_soc_codec_conf max_98390_4spk_codec_conf[] = {  	},  }; -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[] = { +static struct snd_soc_dai_link_component max_98390_components[] = {  	{  		.name = MAX_98390_DEV0_NAME,  		.dai_name = MAX_98390_CODEC_DAI, @@ -219,62 +209,56 @@ struct snd_soc_dai_link_component max_98390_4spk_components[] = {  		.dai_name = MAX_98390_CODEC_DAI,  	},  }; -EXPORT_SYMBOL_NS(max_98390_4spk_components, SND_SOC_INTEL_SOF_MAXIM_COMMON); + +static const struct { +	unsigned int tx; +	unsigned int rx; +} max_98390_tdm_mask[] = { +	{.tx = 0x01, .rx = 0x3}, +	{.tx = 0x02, .rx = 0x3}, +	{.tx = 0x04, .rx = 0x3}, +	{.tx = 0x08, .rx = 0x3}, +};  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; +	int i, ret;  	for_each_rtd_codec_dais(rtd, i, codec_dai) { -		if (i >= ARRAY_SIZE(max_98390_4spk_components)) { +		if (i >= ARRAY_SIZE(max_98390_tdm_mask)) {  			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); +		ret = snd_soc_dai_set_tdm_slot(codec_dai, max_98390_tdm_mask[i].tx, +					       max_98390_tdm_mask[i].rx, 4, +					       params_width(params)); +		if (ret < 0) { +			dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", +				ret); +			return ret;  		}  	}  	return 0;  } -int max_98390_spk_codec_init(struct snd_soc_pcm_runtime *rtd) +static int max_98390_init(struct snd_soc_pcm_runtime *rtd)  {  	struct snd_soc_card *card = rtd->card; +	unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID);  	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)) { +	switch (num_codecs) { +	case 4: +		/* add widgets/controls/dapm for tweeter speakers */  		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); +			dev_err(rtd->dev, "unable to add tweeter dapm widgets, ret %d\n", +				ret);  			/* Don't need to add routes if widget addition failed */  			return ret;  		} @@ -282,33 +266,79 @@ int max_98390_spk_codec_init(struct snd_soc_pcm_runtime *rtd)  		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); +			dev_err(rtd->dev, "unable to add tweeter 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); +		if (ret) { +			dev_err(rtd->dev, "unable to add tweeter dapm routes, ret %d\n", +				ret); +			return ret; +		} + +		fallthrough; +	case 2: +		/* 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 dapm routes, ret %d\n", +				ret); +			return ret; +		} +		break; +	default: +		dev_err(rtd->dev, "invalid codec number %d\n", num_codecs); +		return -EINVAL;  	} +  	return ret;  } -EXPORT_SYMBOL_NS(max_98390_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON); -const struct snd_soc_ops max_98390_ops = { +static 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) +void max_98390_dai_link(struct device *dev, struct snd_soc_dai_link *link) +{ +	unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID); + +	link->codecs = max_98390_components; + +	switch (num_codecs) { +	case 2: +	case 4: +		link->num_codecs = num_codecs; +		break; +	default: +		dev_err(dev, "invalid codec number %d for %s\n", num_codecs, +			MAX_98390_ACPI_HID); +		break; +	} + +	link->init = max_98390_init; +	link->ops = &max_98390_ops; +} +EXPORT_SYMBOL_NS(max_98390_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON); + +void max_98390_set_codec_conf(struct device *dev, struct snd_soc_card *card)  { -	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); +	unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID); + +	card->codec_conf = max_98390_codec_conf; + +	switch (num_codecs) { +	case 2: +	case 4: +		card->num_configs = num_codecs; +		break; +	default: +		dev_err(dev, "invalid codec number %d for %s\n", num_codecs, +			MAX_98390_ACPI_HID); +		break;  	}  }  EXPORT_SYMBOL_NS(max_98390_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);  |