diff options
Diffstat (limited to 'sound/soc/intel/boards/sof_rt5682.c')
| -rw-r--r-- | sound/soc/intel/boards/sof_rt5682.c | 172 | 
1 files changed, 135 insertions, 37 deletions
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 7c034d671cf3..fae091b9b55c 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -22,6 +22,7 @@  #include <sound/soc-acpi.h>  #include "../../codecs/rt5682.h"  #include "../../codecs/rt5682s.h" +#include "../../codecs/rt5645.h"  #include "../../codecs/hdac_hdmi.h"  #include "../common/soc-intel-quirks.h"  #include "hda_dsp_common.h" @@ -58,9 +59,14 @@  #define SOF_SSP_BT_OFFLOAD_PRESENT		BIT(22)  #define SOF_RT5682S_HEADPHONE_CODEC_PRESENT	BIT(23)  #define SOF_MAX98390_SPEAKER_AMP_PRESENT	BIT(24) -#define SOF_MAX98390_TWEETER_SPEAKER_PRESENT	BIT(25)  #define SOF_RT1019_SPEAKER_AMP_PRESENT	BIT(26) +#define SOF_RT5650_HEADPHONE_CODEC_PRESENT	BIT(27) +/* HDMI capture*/ +#define SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT  27 +#define SOF_SSP_HDMI_CAPTURE_PRESENT_MASK (GENMASK(30, 27)) +#define SOF_HDMI_CAPTURE_SSP_MASK(quirk)   \ +	(((quirk) << SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT) & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK)  /* Default: MCLK on, MCLK 19.2M, SSP0  */  static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | @@ -197,23 +203,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {  		.callback = sof_rt5682_quirk_cb,  		.matches = {  			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"), -			DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S_4SPK"), -		}, -		.driver_data = (void *)(SOF_RT5682_MCLK_EN | -					SOF_RT5682_SSP_CODEC(0) | -					SOF_SPEAKER_AMP_PRESENT | -					SOF_MAX98390_SPEAKER_AMP_PRESENT | -					SOF_MAX98390_TWEETER_SPEAKER_PRESENT | -					SOF_RT5682_SSP_AMP(1) | -					SOF_RT5682_NUM_HDMIDEV(4) | -					SOF_BT_OFFLOAD_SSP(2) | -					SOF_SSP_BT_OFFLOAD_PRESENT), - -	}, -	{ -		.callback = sof_rt5682_quirk_cb, -		.matches = { -			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),  			DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"),  		},  		.driver_data = (void *)(SOF_RT5682_MCLK_EN | @@ -305,6 +294,7 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)  	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);  	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;  	struct snd_soc_jack *jack; +	int extra_jack_data;  	int ret;  	/* need to enable ASRC function for 24MHz mclk rate */ @@ -315,7 +305,16 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)  						 RT5682S_DA_STEREO1_FILTER |  						 RT5682S_AD_STEREO1_FILTER,  						 RT5682S_CLK_SEL_I2S1_ASRC); -		else +		else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { +			rt5645_sel_asrc_clk_src(component, +						RT5645_DA_STEREO_FILTER | +						RT5645_AD_STEREO_FILTER, +						RT5645_CLK_SEL_I2S1_ASRC); +			rt5645_sel_asrc_clk_src(component, +						RT5645_DA_MONO_L_FILTER | +						RT5645_DA_MONO_R_FILTER, +						RT5645_CLK_SEL_I2S2_ASRC); +		} else  			rt5682_sel_asrc_clk_src(component,  						RT5682_DA_STEREO1_FILTER |  						RT5682_AD_STEREO1_FILTER, @@ -365,7 +364,12 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)  	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);  	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);  	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); -	ret = snd_soc_component_set_jack(component, jack, NULL); + +	if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { +		extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0; +		ret = snd_soc_component_set_jack(component, jack, &extra_jack_data); +	} else +		ret = snd_soc_component_set_jack(component, jack, NULL);  	if (ret) {  		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); @@ -402,6 +406,8 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,  		if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)  			pll_source = RT5682S_PLL_S_MCLK; +		else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) +			pll_source = RT5645_PLL1_S_MCLK;  		else  			pll_source = RT5682_PLL1_S_MCLK; @@ -422,6 +428,8 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,  	} else {  		if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)  			pll_source = RT5682S_PLL_S_BCLK1; +		else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) +			pll_source = RT5645_PLL1_S_BCLK1;  		else  			pll_source = RT5682_PLL1_S_BCLK1; @@ -431,6 +439,9 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,  	if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {  		pll_id = RT5682S_PLL2;  		clk_id = RT5682S_SCLK_S_PLL2; +	} else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { +		pll_id = 0; /* not used in codec driver */ +		clk_id = RT5645_SCLK_S_PLL1;  	} else {  		pll_id = RT5682_PLL1;  		clk_id = RT5682_SCLK_S_PLL1; @@ -559,11 +570,30 @@ static const struct snd_soc_dapm_route sof_map[] = {  	{ "IN1P", NULL, "Headset Mic" },  }; +static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = { +	/* speaker */ +	{ "Left Spk", NULL, "SPOL" }, +	{ "Right Spk", NULL, "SPOR" }, +}; +  static const struct snd_soc_dapm_route dmic_map[] = {  	/* digital mics */  	{"DMic", NULL, "SoC DMIC"},  }; +static int rt5650_spk_init(struct snd_soc_pcm_runtime *rtd) +{ +	struct snd_soc_card *card = rtd->card; +	int ret; + +	ret = snd_soc_dapm_add_routes(&card->dapm, rt5650_spk_dapm_routes, +				      ARRAY_SIZE(rt5650_spk_dapm_routes)); +	if (ret) +		dev_err(rtd->dev, "fail to add dapm routes, ret=%d\n", ret); + +	return ret; +} +  static int dmic_init(struct snd_soc_pcm_runtime *rtd)  {  	struct snd_soc_card *card = rtd->card; @@ -614,6 +644,17 @@ static struct snd_soc_dai_link_component rt5682s_component[] = {  	}  }; +static struct snd_soc_dai_link_component rt5650_components[] = { +	{ +		.name = "i2c-10EC5650:00", +		.dai_name = "rt5645-aif1", +	}, +	{ +		.name = "i2c-10EC5650:00", +		.dai_name = "rt5645-aif2", +	} +}; +  static struct snd_soc_dai_link_component dmic_component[] = {  	{  		.name = "dmic-codec", @@ -634,6 +675,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,  	struct snd_soc_dai_link_component *cpus;  	struct snd_soc_dai_link *links;  	int i, id = 0; +	int hdmi_id_offset = 0;  	links = devm_kcalloc(dev, sof_audio_card_rt5682.num_links,  			    sizeof(struct snd_soc_dai_link), GFP_KERNEL); @@ -652,6 +694,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,  	if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {  		links[id].codecs = rt5682s_component;  		links[id].num_codecs = ARRAY_SIZE(rt5682s_component); +	} else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { +		links[id].codecs = &rt5650_components[0]; +		links[id].num_codecs = 1;  	} else {  		links[id].codecs = rt5682_component;  		links[id].num_codecs = ARRAY_SIZE(rt5682_component); @@ -793,17 +838,12 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,  			sof_rt1011_dai_link(&links[id]);  		} else if (sof_rt5682_quirk &  				SOF_MAX98390_SPEAKER_AMP_PRESENT) { -			if (sof_rt5682_quirk & -				SOF_MAX98390_TWEETER_SPEAKER_PRESENT) { -				links[id].codecs = max_98390_4spk_components; -				links[id].num_codecs = ARRAY_SIZE(max_98390_4spk_components); -			} else { -				links[id].codecs = max_98390_components; -				links[id].num_codecs = ARRAY_SIZE(max_98390_components); -			} -			links[id].init = max_98390_spk_codec_init; -			links[id].ops = &max_98390_ops; - +			max_98390_dai_link(dev, &links[id]); +		} else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { +			links[id].codecs = &rt5650_components[1]; +			links[id].num_codecs = 1; +			links[id].init = rt5650_spk_init; +			links[id].ops = &sof_rt5682_ops;  		} else {  			max_98357a_dai_link(&links[id]);  		} @@ -857,6 +897,34 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,  		links[id].num_cpus = 1;  	} +	/* HDMI-In SSP */ +	if (sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) { +		unsigned long hdmi_in_ssp = (sof_rt5682_quirk & +				SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) >> +				SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; +		int port = 0; + +		for_each_set_bit(port, &hdmi_in_ssp, 32) { +			links[id].cpus = &cpus[id]; +			links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, +								  "SSP%d Pin", port); +			if (!links[id].cpus->dai_name) +				return NULL; +			links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", port); +			if (!links[id].name) +				return NULL; +			links[id].id = id + hdmi_id_offset; +			links[id].codecs = &asoc_dummy_dlc; +			links[id].num_codecs = 1; +			links[id].platforms = platform_component; +			links[id].num_platforms = ARRAY_SIZE(platform_component); +			links[id].dpcm_capture = 1; +			links[id].no_pcm = 1; +			links[id].num_cpus = 1; +			id++; +		} +	} +  	return links;  devm_err:  	return NULL; @@ -890,6 +958,12 @@ static int sof_audio_probe(struct platform_device *pdev)  	/* Detect the headset codec variant */  	if (acpi_dev_present("RTL5682", NULL, -1))  		sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT; +	else if (acpi_dev_present("10EC5650", NULL, -1)) { +		sof_rt5682_quirk |= SOF_RT5650_HEADPHONE_CODEC_PRESENT; + +		sof_audio_card_rt5682.name = devm_kstrdup(&pdev->dev, "rt5650", +							  GFP_KERNEL); +	}  	if (soc_intel_is_byt() || soc_intel_is_cht()) {  		is_legacy_cpu = 1; @@ -951,17 +1025,17 @@ static int sof_audio_probe(struct platform_device *pdev)  	else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)  		sof_rt1015p_codec_conf(&sof_audio_card_rt5682);  	else if (sof_rt5682_quirk & SOF_MAX98390_SPEAKER_AMP_PRESENT) { -		if (sof_rt5682_quirk & SOF_MAX98390_TWEETER_SPEAKER_PRESENT) -			max_98390_set_codec_conf(&sof_audio_card_rt5682, -						 ARRAY_SIZE(max_98390_4spk_components)); -		else -			max_98390_set_codec_conf(&sof_audio_card_rt5682, -						 ARRAY_SIZE(max_98390_components)); +		max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);  	}  	if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)  		sof_audio_card_rt5682.num_links++; +	if (sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) +		sof_audio_card_rt5682.num_links += +			hweight32((sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) >> +					SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT); +  	dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,  					      dmic_be_num, hdmi_num, ctx->idisp_codec);  	if (!dai_links) @@ -1129,6 +1203,22 @@ static const struct platform_device_id board_ids[] = {  					SOF_SSP_BT_OFFLOAD_PRESENT),  	},  	{ +		.name = "adl_rt5682_c1_h02", +		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | +					SOF_RT5682_SSP_CODEC(1) | +					SOF_RT5682_NUM_HDMIDEV(3) | +					/* SSP 0 and SSP 2 are used for HDMI IN */ +					SOF_HDMI_CAPTURE_SSP_MASK(0x5)), +	}, +	{ +		.name = "rpl_mx98357_rt5682", +		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | +					SOF_RT5682_SSP_CODEC(0) | +					SOF_SPEAKER_AMP_PRESENT | +					SOF_RT5682_SSP_AMP(2) | +					SOF_RT5682_NUM_HDMIDEV(4)), +	}, +	{  		.name = "rpl_mx98360_rt5682",  		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |  					SOF_RT5682_SSP_CODEC(0) | @@ -1178,6 +1268,14 @@ static const struct platform_device_id board_ids[] = {  					SOF_RT5682_SSP_AMP(0) |  					SOF_RT5682_NUM_HDMIDEV(3)),  	}, +	{ +		.name = "jsl_rt5650", +		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | +					SOF_RT5682_MCLK_24MHZ | +					SOF_RT5682_SSP_CODEC(0) | +					SOF_SPEAKER_AMP_PRESENT | +					SOF_RT5682_SSP_AMP(1)), +	},  	{ }  };  MODULE_DEVICE_TABLE(platform, board_ids);  |