diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 44168d6f0fd541..771bdf483d3814 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -318,16 +318,20 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH endif ## SND_SOC_INTEL_SKYLAKE -if SND_SOC_INTEL_SKL || SND_SOC_SOF_CANNONLAKE +if SND_SOC_INTEL_SKYLAKE || SND_SOC_SOF_CANNONLAKE config SND_SOC_INTEL_CNL_RT274_MACH - tristate "ASoC Audio driver for CNL with RT274 in I2S Mode" - select SND_SOC_RT274 + tristate "Cannonlake with RT274 I2S mode" + depends on MFD_INTEL_LPSS && I2C && ACPI + select SND_SOC_RT274 + select SND_SOC_DMIC + select SND_SOC_HDAC_HDMI help - This adds support for ASoC machine driver for CNL and codec RT274. This - will create an alsa sound card. Say Y if you have such a device If - unsure select "N". + This adds support for ASoC machine driver for Cannonlake platform + with RT274 I2S audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". -endif ## SND_SOC_INTEL_SKL || SND_SOC_SOF_CANNONLAKE +endif ## SND_SOC_INTEL_SKYLAKE endif ## SND_SOC_INTEL_MACH diff --git a/sound/soc/intel/boards/cnl_rt274.c b/sound/soc/intel/boards/cnl_rt274.c index 16daa31b8d2ca0..0689c63304ea46 100644 --- a/sound/soc/intel/boards/cnl_rt274.c +++ b/sound/soc/intel/boards/cnl_rt274.c @@ -19,9 +19,20 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include + #include "../../codecs/rt274.h" #define CNL_FREQ_OUT 24000000 @@ -41,19 +52,32 @@ static int cnl_rt274_clock_control(struct snd_soc_dapm_widget *w, if (!codec_dai) return -EINVAL; - ret = snd_soc_dai_set_sysclk(codec_dai, RT274_SCLK_S_PLL1, - CNL_FREQ_OUT, - SND_SOC_CLOCK_IN); - if (ret) { - dev_err(codec_dai->dev, - "failed to enable PLL1: %d\n", ret); + /* Codec needs clock for Jack detection and button press */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT274_SCLK_S_PLL2, + CNL_FREQ_OUT, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "set codec sysclk failed: %d\n", ret); + return ret; } - snd_soc_dai_set_bclk_ratio(codec_dai, ratio); + if (SND_SOC_DAPM_EVENT_ON(event)) { + snd_soc_dai_set_bclk_ratio(codec_dai, ratio); + + ret = snd_soc_dai_set_pll(codec_dai, 0, RT274_PLL2_S_BCLK, + CNL_BE_FIXUP_RATE * ratio, + CNL_FREQ_OUT); + if (ret) { + dev_err(codec_dai->dev, + "failed to enable PLL2: %d\n", ret); + return ret; + } + } return ret; } +static struct snd_soc_jack cnl_headset; + /* Headset jack detection DAPM pins */ static struct snd_soc_jack_pin cnl_headset_pins[] = { { @@ -80,13 +104,17 @@ static const struct snd_soc_dapm_widget cnl_rt274_widgets[] = { SND_SOC_DAPM_POST_PMD), }; -static const struct snd_soc_pcm_stream dai_params_codec = { - .formats = SNDRV_PCM_FMTBIT_S24_LE, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, -}; +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL) +static int cnl_dmic_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + channels->min = channels->max = 2; + + return 0; +} +#endif static const struct snd_soc_dapm_route cnl_map[] = { {"Headphone Jack", NULL, "HPO Pin"}, @@ -95,6 +123,17 @@ static const struct snd_soc_dapm_route cnl_map[] = { {"DMIC01 Rx", NULL, "Capture"}, {"dmic01_hifi", NULL, "DMIC01 Rx"}, + /* ssp2 path */ + {"Dummy Playback", NULL, "ssp2 Tx"}, + {"ssp2 Tx", NULL, "ssp2_out"}, + + {"ssp2 Rx", NULL, "Dummy Capture"}, + {"ssp2_in", NULL, "ssp2 Rx"}, + + /* ssp1 path */ + {"Dummy Playback", NULL, "ssp1 Tx"}, + {"ssp1 Tx", NULL, "ssp1_out"}, + {"AIF1 Playback", NULL, "ssp0 Tx"}, {"ssp0 Tx", NULL, "codec1_out"}, {"ssp0 Tx", NULL, "codec0_out"}, @@ -106,14 +145,12 @@ static const struct snd_soc_dapm_route cnl_map[] = { {"MIC", NULL, "Platform Clock"}, }; -static struct snd_soc_jack cnl_headset; - static int cnl_rt274_init(struct snd_soc_pcm_runtime *runtime) { int ret; + struct snd_soc_component *component = runtime->codec_dai->component; struct snd_soc_card *card = runtime->card; struct snd_soc_dai *codec_dai = runtime->codec_dai; - struct snd_soc_component *component = codec_dai->component; ret = snd_soc_card_jack_new(runtime->card, "Headset", SND_JACK_HEADSET, &cnl_headset, @@ -151,34 +188,99 @@ static int cnl_be_fixup(struct snd_soc_pcm_runtime *rtd, channels->max = 2; snd_mask_none(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT)); snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), - SNDRV_PCM_FORMAT_S24_LE); + (unsigned int __force)SNDRV_PCM_FORMAT_S24_LE); return 0; } -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL) -static int cnl_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - channels->min = 2; - channels->max = 2; - - return 0; -} +#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CNL_FPGA) +static const char pname[] = "0000:02:18.0"; +static const char cname[] = "rt274.0-001c"; +#else +#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL) +static const char pname[] = "sof-audio"; +#else +static const char pname[] = "0000:00:1f.3"; #endif - static const char cname[] = "i2c-INT34C2:00"; +#endif -static struct snd_soc_dai_link cnl_rt274_dailink[] = { +static struct snd_soc_dai_link cnl_rt274_msic_dailink[] = { +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL) + /* Trace Buffer DAI links */ + { + .name = "CNL Trace Buffer0", + .stream_name = "Core 0 Trace Buffer", + .cpu_dai_name = "TraceBuffer0 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = pname, + .capture_only = true, + .ignore_suspend = 1, + }, + { + .name = "CNL Trace Buffer1", + .stream_name = "Core 1 Trace Buffer", + .cpu_dai_name = "TraceBuffer1 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = pname, + .capture_only = true, + .ignore_suspend = 1, + }, + { + .name = "CNL Trace Buffer2", + .stream_name = "Core 2 Trace Buffer", + .cpu_dai_name = "TraceBuffer2 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = pname, + .capture_only = true, + .ignore_suspend = 1, + }, + { + .name = "CNL Trace Buffer3", + .stream_name = "Core 3 Trace Buffer", + .cpu_dai_name = "TraceBuffer3 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = pname, + .capture_only = true, + .ignore_suspend = 1, + }, + /* Probe DAI-links */ + { + .name = "CNL Compress Probe playback", + .stream_name = "Probe Playback", + .cpu_dai_name = "Compress Probe0 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = pname, + .init = NULL, + .ignore_suspend = 1, + .nonatomic = 1, + }, + { + .name = "CNL Compress Probe capture", + .stream_name = "Probe Capture", + .cpu_dai_name = "Compress Probe1 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = pname, + .init = NULL, + .ignore_suspend = 1, + .nonatomic = 1, + }, +#endif + /* back ends */ { .name = "SSP0-Codec", + .id = 1, .cpu_dai_name = "SSP0 Pin", .codec_name = cname, .codec_dai_name = "rt274-aif1", .be_hw_params_fixup = cnl_be_fixup, - .ignore_pmdown_time = 1, + .ignore_suspend = 1, .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, @@ -189,6 +291,7 @@ static struct snd_soc_dai_link cnl_rt274_dailink[] = { #if !IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL) { .name = "dmic01", + .id = 2, .cpu_dai_name = "DMIC01 Pin", .codec_name = "dmic-codec", .codec_dai_name = "dmic-hifi", @@ -200,42 +303,45 @@ static struct snd_soc_dai_link cnl_rt274_dailink[] = { #endif }; +static int +cnl_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) +{ + link->platform_name = pname; + link->nonatomic = 1; + + return 0; +} + /* SoC card */ static struct snd_soc_card snd_soc_card_cnl = { .name = "cnl-audio", - .dai_link = cnl_rt274_dailink, - .num_links = ARRAY_SIZE(cnl_rt274_dailink), + .dai_link = cnl_rt274_msic_dailink, + .num_links = ARRAY_SIZE(cnl_rt274_msic_dailink), .dapm_widgets = cnl_rt274_widgets, .num_dapm_widgets = ARRAY_SIZE(cnl_rt274_widgets), .dapm_routes = cnl_map, .num_dapm_routes = ARRAY_SIZE(cnl_map), .controls = cnl_controls, .num_controls = ARRAY_SIZE(cnl_controls), + .add_dai_link = cnl_add_dai_link, .fully_routed = true, }; -static int cnl_rt274_probe(struct platform_device *pdev) +static int snd_cnl_rt274_mc_probe(struct platform_device *pdev) { snd_soc_card_cnl.dev = &pdev->dev; - return devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cnl); } -static const struct platform_device_id cnl_board_ids[] = { - { .name = "cnl_rt274" }, - { } -}; - -static struct platform_driver cnl_rt274_driver = { +static struct platform_driver snd_cnl_rt274_driver = { .driver = { .name = "cnl_rt274", .pm = &snd_soc_pm_ops, }, - .probe = cnl_rt274_probe, - .id_table = cnl_board_ids, + .probe = snd_cnl_rt274_mc_probe, }; -module_platform_driver(cnl_rt274_driver); +module_platform_driver(snd_cnl_rt274_driver); MODULE_AUTHOR("Guneshwor Singh "); MODULE_LICENSE("GPL v2");