diff options
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r-- | sound/soc/fsl/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/fsl/efika-audio-fabric.c | 22 | ||||
-rw-r--r-- | sound/soc/fsl/eukrea-tlv320.c | 19 | ||||
-rw-r--r-- | sound/soc/fsl/fsl-asoc-card.c | 47 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_asrc.c | 103 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_esai.c | 141 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_sai.c | 54 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 4 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_ssi.h | 8 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_ssi_dbg.c | 18 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_utils.c | 2 | ||||
-rw-r--r-- | sound/soc/fsl/imx-audmix.c | 45 | ||||
-rw-r--r-- | sound/soc/fsl/imx-audmux.c | 10 | ||||
-rw-r--r-- | sound/soc/fsl/imx-es8328.c | 23 | ||||
-rw-r--r-- | sound/soc/fsl/imx-mc13783.c | 10 | ||||
-rw-r--r-- | sound/soc/fsl/imx-pcm-dma.c | 6 | ||||
-rw-r--r-- | sound/soc/fsl/imx-sgtl5000.c | 23 | ||||
-rw-r--r-- | sound/soc/fsl/imx-spdif.c | 20 | ||||
-rw-r--r-- | sound/soc/fsl/mpc8610_hpcd.c | 33 | ||||
-rw-r--r-- | sound/soc/fsl/mx27vis-aic32x4.c | 11 | ||||
-rw-r--r-- | sound/soc/fsl/p1022_ds.c | 36 | ||||
-rw-r--r-- | sound/soc/fsl/p1022_rdk.c | 35 | ||||
-rw-r--r-- | sound/soc/fsl/pcm030-audio-fabric.c | 20 | ||||
-rw-r--r-- | sound/soc/fsl/phycore-ac97.c | 10 | ||||
-rw-r--r-- | sound/soc/fsl/wm1133-ev1.c | 10 |
25 files changed, 474 insertions, 237 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 55ed47c599e2..aa99c008a925 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only menu "SoC Audio for Freescale CPUs" comment "Common SoC Audio options for Freescale CPUs:" diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index 667f4215dfc0..8f6396faec9b 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c @@ -29,22 +29,28 @@ #define DRV_NAME "efika-audio-fabric" +SND_SOC_DAILINK_DEFS(analog, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("stac9766-codec", + "stac9766-hifi-analog")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("mpc5200-pcm-audio"))); + +SND_SOC_DAILINK_DEFS(iec958, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("stac9766-codec", + "stac9766-hifi-IEC958")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("mpc5200-pcm-audio"))); + static struct snd_soc_dai_link efika_fabric_dai[] = { { .name = "AC97", .stream_name = "AC97 Analog", - .codec_dai_name = "stac9766-hifi-analog", - .cpu_dai_name = "mpc5200-psc-ac97.0", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "stac9766-codec", + SND_SOC_DAILINK_REG(analog), }, { .name = "AC97", .stream_name = "AC97 IEC958", - .codec_dai_name = "stac9766-hifi-IEC958", - .cpu_dai_name = "mpc5200-psc-ac97.1", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "stac9766-codec", + SND_SOC_DAILINK_REG(iec958), }, }; diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index d648268cb454..6f3b768489f6 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -61,13 +61,18 @@ static const struct snd_soc_ops eukrea_tlv320_snd_ops = { .hw_params = eukrea_tlv320_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic23-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", - .codec_dai_name = "tlv320aic23-hifi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &eukrea_tlv320_snd_ops, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card eukrea_tlv320 = { @@ -104,7 +109,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) codec_np = of_parse_phandle(ssi_np, "codec-handle", 0); if (codec_np) - eukrea_tlv320_dai.codec_of_node = codec_np; + eukrea_tlv320_dai.codecs->of_node = codec_np; else dev_err(&pdev->dev, "codec-handle node missing or invalid.\n"); @@ -128,12 +133,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) int_port--; ext_port--; - eukrea_tlv320_dai.cpu_of_node = ssi_np; - eukrea_tlv320_dai.platform_of_node = ssi_np; + eukrea_tlv320_dai.cpus->of_node = ssi_np; + eukrea_tlv320_dai.platforms->of_node = ssi_np; } else { - eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0"; - eukrea_tlv320_dai.platform_name = "imx-ssi.0"; - eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a"; + eukrea_tlv320_dai.cpus->dai_name = "imx-ssi.0"; + eukrea_tlv320_dai.platforms->name = "imx-ssi.0"; + eukrea_tlv320_dai.codecs->name = "tlv320aic23-codec.0-001a"; eukrea_tlv320.name = "cpuimx-audio"; } diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 60f87a0d99f4..39ea9bda1394 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -200,32 +200,47 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_fe, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_be, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY())); + static struct snd_soc_dai_link fsl_asoc_card_dai[] = { /* Default ASoC DAI Link*/ { .name = "HiFi", .stream_name = "HiFi", .ops = &fsl_asoc_card_ops, + SND_SOC_DAILINK_REG(hifi), }, /* DPCM Link between Front-End and Back-End (Optional) */ { .name = "HiFi-ASRC-FE", .stream_name = "HiFi-ASRC-FE", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", .dpcm_playback = 1, .dpcm_capture = 1, .dynamic = 1, + SND_SOC_DAILINK_REG(hifi_fe), }, { .name = "HiFi-ASRC-BE", .stream_name = "HiFi-ASRC-BE", - .platform_name = "snd-soc-dummy", .be_hw_params_fixup = be_hw_params_fixup, .ops = &fsl_asoc_card_ops, .dpcm_playback = 1, .dpcm_capture = 1, .no_pcm = 1, + SND_SOC_DAILINK_REG(hifi_be), }, }; @@ -616,11 +631,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } /* Normal DAI Link */ - priv->dai_link[0].cpu_of_node = cpu_np; - priv->dai_link[0].codec_dai_name = codec_dai_name; + priv->dai_link[0].cpus->of_node = cpu_np; + priv->dai_link[0].codecs->dai_name = codec_dai_name; if (!fsl_asoc_card_is_ac97(priv)) - priv->dai_link[0].codec_of_node = codec_np; + priv->dai_link[0].codecs->of_node = codec_np; else { u32 idx; @@ -631,29 +646,29 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto asrc_fail; } - priv->dai_link[0].codec_name = + priv->dai_link[0].codecs->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ac97-codec.%u", (unsigned int)idx); - if (!priv->dai_link[0].codec_name) { + if (!priv->dai_link[0].codecs->name) { ret = -ENOMEM; goto asrc_fail; } } - priv->dai_link[0].platform_of_node = cpu_np; + priv->dai_link[0].platforms->of_node = cpu_np; priv->dai_link[0].dai_fmt = priv->dai_fmt; priv->card.num_links = 1; if (asrc_pdev) { /* DPCM DAI Links only if ASRC exsits */ - priv->dai_link[1].cpu_of_node = asrc_np; - priv->dai_link[1].platform_of_node = asrc_np; - priv->dai_link[2].codec_dai_name = codec_dai_name; - priv->dai_link[2].codec_of_node = codec_np; - priv->dai_link[2].codec_name = - priv->dai_link[0].codec_name; - priv->dai_link[2].cpu_of_node = cpu_np; + priv->dai_link[1].cpus->of_node = asrc_np; + priv->dai_link[1].platforms->of_node = asrc_np; + priv->dai_link[2].codecs->dai_name = codec_dai_name; + priv->dai_link[2].codecs->of_node = codec_np; + priv->dai_link[2].codecs->name = + priv->dai_link[0].codecs->name; + priv->dai_link[2].cpus->of_node = cpu_np; priv->dai_link[2].dai_fmt = priv->dai_fmt; priv->card.num_links = 3; diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index ea035c12a325..cbbf6257f08a 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -26,32 +26,15 @@ #define pair_dbg(fmt, ...) \ dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) -/* Sample rates are aligned with that defined in pcm.h file */ -static const u8 process_option[][12][2] = { - /* 8kHz 11.025kHz 16kHz 22.05kHz 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */ - {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */ - {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */ - {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */ - {{1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */ - {{1, 2}, {1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */ - {{1, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */ - {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */ - {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */ - {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */ -}; - /* Corresponding to process_option */ -static int supported_input_rate[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, - 96000, 176400, 192000, +static unsigned int supported_asrc_rate[] = { + 5512, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, + 64000, 88200, 96000, 128000, 176400, 192000, }; -static int supported_asrc_rate[] = { - 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, +static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints = { + .count = ARRAY_SIZE(supported_asrc_rate), + .list = supported_asrc_rate, }; /** @@ -80,6 +63,52 @@ static unsigned char output_clk_map_imx53[] = { static unsigned char *clk_map[2]; /** + * Select the pre-processing and post-processing options + * Make sure to exclude following unsupported cases before + * calling this function: + * 1) inrate > 8.125 * outrate + * 2) inrate > 16.125 * outrate + * + * inrate: input sample rate + * outrate: output sample rate + * pre_proc: return value for pre-processing option + * post_proc: return value for post-processing option + */ +static void fsl_asrc_sel_proc(int inrate, int outrate, + int *pre_proc, int *post_proc) +{ + bool post_proc_cond2; + bool post_proc_cond0; + + /* select pre_proc between [0, 2] */ + if (inrate * 8 > 33 * outrate) + *pre_proc = 2; + else if (inrate * 8 > 15 * outrate) { + if (inrate > 152000) + *pre_proc = 2; + else + *pre_proc = 1; + } else if (inrate < 76000) + *pre_proc = 0; + else if (inrate > 152000) + *pre_proc = 2; + else + *pre_proc = 1; + + /* Condition for selection of post-processing */ + post_proc_cond2 = (inrate * 15 > outrate * 16 && outrate < 56000) || + (inrate > 56000 && outrate < 56000); + post_proc_cond0 = inrate * 23 < outrate * 8; + + if (post_proc_cond2) + *post_proc = 2; + else if (post_proc_cond0) + *post_proc = 0; + else + *post_proc = 1; +} + +/** * Request ASRC pair * * It assigns pair by the order of A->C->B because allocation of pair B, @@ -239,6 +268,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) u32 inrate, outrate, indiv, outdiv; u32 clk_index[2], div[2]; int in, out, channels; + int pre_proc, post_proc; struct clk *clk; bool ideal; @@ -264,11 +294,11 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) ideal = config->inclk == INCLK_NONE; /* Validate input and output sample rates */ - for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++) - if (inrate == supported_input_rate[in]) + for (in = 0; in < ARRAY_SIZE(supported_asrc_rate); in++) + if (inrate == supported_asrc_rate[in]) break; - if (in == ARRAY_SIZE(supported_input_rate)) { + if (in == ARRAY_SIZE(supported_asrc_rate)) { pair_err("unsupported input sample rate: %dHz\n", inrate); return -EINVAL; } @@ -282,7 +312,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) return -EINVAL; } - if ((outrate >= 8000 && outrate <= 30000) && + if ((outrate >= 5512 && outrate <= 30000) && (outrate > 24 * inrate || inrate > 8 * outrate)) { pair_err("exceed supported ratio range [1/24, 8] for \ inrate/outrate: %d/%d\n", inrate, outrate); @@ -377,11 +407,13 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index), ASRCTR_IDR(index) | ASRCTR_USR(index)); + fsl_asrc_sel_proc(inrate, outrate, &pre_proc, &post_proc); + /* Apply configurations for pre- and post-processing */ regmap_update_bits(asrc_priv->regmap, REG_ASRCFG, ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index), - ASRCFG_PREMOD(index, process_option[in][out][0]) | - ASRCFG_POSTMOD(index, process_option[in][out][1])); + ASRCFG_PREMOD(index, pre_proc) | + ASRCFG_POSTMOD(index, post_proc)); return fsl_asrc_set_ideal_ratio(pair, inrate, outrate); } @@ -455,7 +487,9 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream, snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - return 0; + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints); } static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, @@ -568,7 +602,6 @@ static int fsl_asrc_dai_probe(struct snd_soc_dai *dai) return 0; } -#define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000 #define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S20_3LE) @@ -579,14 +612,18 @@ static struct snd_soc_dai_driver fsl_asrc_dai = { .stream_name = "ASRC-Playback", .channels_min = 1, .channels_max = 10, - .rates = FSL_ASRC_RATES, + .rate_min = 5512, + .rate_max = 192000, + .rates = SNDRV_PCM_RATE_KNOT, .formats = FSL_ASRC_FORMATS, }, .capture = { .stream_name = "ASRC-Capture", .channels_min = 1, .channels_max = 10, - .rates = FSL_ASRC_RATES, + .rate_min = 5512, + .rate_max = 192000, + .rates = SNDRV_PCM_RATE_KNOT, .formats = FSL_ASRC_FORMATS, }, .ops = &fsl_asrc_dai_ops, diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index bad0dfed6b68..10d2210c91ef 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/pm_runtime.h> #include <sound/dmaengine_pcm.h> #include <sound/pcm_params.h> @@ -466,30 +467,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); - int ret; - - /* - * Some platforms might use the same bit to gate all three or two of - * clocks, so keep all clocks open/close at the same time for safety - */ - ret = clk_prepare_enable(esai_priv->coreclk); - if (ret) - return ret; - if (!IS_ERR(esai_priv->spbaclk)) { - ret = clk_prepare_enable(esai_priv->spbaclk); - if (ret) - goto err_spbaclk; - } - if (!IS_ERR(esai_priv->extalclk)) { - ret = clk_prepare_enable(esai_priv->extalclk); - if (ret) - goto err_extalck; - } - if (!IS_ERR(esai_priv->fsysclk)) { - ret = clk_prepare_enable(esai_priv->fsysclk); - if (ret) - goto err_fsysclk; - } if (!dai->active) { /* Set synchronous mode */ @@ -506,16 +483,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, return 0; -err_fsysclk: - if (!IS_ERR(esai_priv->extalclk)) - clk_disable_unprepare(esai_priv->extalclk); -err_extalck: - if (!IS_ERR(esai_priv->spbaclk)) - clk_disable_unprepare(esai_priv->spbaclk); -err_spbaclk: - clk_disable_unprepare(esai_priv->coreclk); - - return ret; } static int fsl_esai_hw_params(struct snd_pcm_substream *substream, @@ -576,20 +543,6 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, return 0; } -static void fsl_esai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); - - if (!IS_ERR(esai_priv->fsysclk)) - clk_disable_unprepare(esai_priv->fsysclk); - if (!IS_ERR(esai_priv->extalclk)) - clk_disable_unprepare(esai_priv->extalclk); - if (!IS_ERR(esai_priv->spbaclk)) - clk_disable_unprepare(esai_priv->spbaclk); - clk_disable_unprepare(esai_priv->coreclk); -} - static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -658,7 +611,6 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, static const struct snd_soc_dai_ops fsl_esai_dai_ops = { .startup = fsl_esai_startup, - .shutdown = fsl_esai_shutdown, .trigger = fsl_esai_trigger, .hw_params = fsl_esai_hw_params, .set_sysclk = fsl_esai_set_dai_sysclk, @@ -947,6 +899,10 @@ static int fsl_esai_probe(struct platform_device *pdev) return ret; } + pm_runtime_enable(&pdev->dev); + + regcache_cache_only(esai_priv->regmap, true); + ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE); if (ret) dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); @@ -954,6 +910,13 @@ static int fsl_esai_probe(struct platform_device *pdev) return ret; } +static int fsl_esai_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + static const struct of_device_id fsl_esai_dt_ids[] = { { .compatible = "fsl,imx35-esai", }, { .compatible = "fsl,vf610-esai", }, @@ -961,22 +924,35 @@ static const struct of_device_id fsl_esai_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); -#ifdef CONFIG_PM_SLEEP -static int fsl_esai_suspend(struct device *dev) -{ - struct fsl_esai *esai = dev_get_drvdata(dev); - - regcache_cache_only(esai->regmap, true); - regcache_mark_dirty(esai->regmap); - - return 0; -} - -static int fsl_esai_resume(struct device *dev) +#ifdef CONFIG_PM +static int fsl_esai_runtime_resume(struct device *dev) { struct fsl_esai *esai = dev_get_drvdata(dev); int ret; + /* + * Some platforms might use the same bit to gate all three or two of + * clocks, so keep all clocks open/close at the same time for safety + */ + ret = clk_prepare_enable(esai->coreclk); + if (ret) + return ret; + if (!IS_ERR(esai->spbaclk)) { + ret = clk_prepare_enable(esai->spbaclk); + if (ret) + goto err_spbaclk; + } + if (!IS_ERR(esai->extalclk)) { + ret = clk_prepare_enable(esai->extalclk); + if (ret) + goto err_extalclk; + } + if (!IS_ERR(esai->fsysclk)) { + ret = clk_prepare_enable(esai->fsysclk); + if (ret) + goto err_fsysclk; + } + regcache_cache_only(esai->regmap, false); /* FIFO reset for safety */ @@ -987,22 +963,59 @@ static int fsl_esai_resume(struct device *dev) ret = regcache_sync(esai->regmap); if (ret) - return ret; + goto err_regcache_sync; /* FIFO reset done */ regmap_update_bits(esai->regmap, REG_ESAI_TFCR, ESAI_xFCR_xFR, 0); regmap_update_bits(esai->regmap, REG_ESAI_RFCR, ESAI_xFCR_xFR, 0); return 0; + +err_regcache_sync: + if (!IS_ERR(esai->fsysclk)) + clk_disable_unprepare(esai->fsysclk); +err_fsysclk: + if (!IS_ERR(esai->extalclk)) + clk_disable_unprepare(esai->extalclk); +err_extalclk: + if (!IS_ERR(esai->spbaclk)) + clk_disable_unprepare(esai->spbaclk); +err_spbaclk: + clk_disable_unprepare(esai->coreclk); + + return ret; +} + +static int fsl_esai_runtime_suspend(struct device *dev) +{ + struct fsl_esai *esai = dev_get_drvdata(dev); + + regcache_cache_only(esai->regmap, true); + regcache_mark_dirty(esai->regmap); + + if (!IS_ERR(esai->fsysclk)) + clk_disable_unprepare(esai->fsysclk); + if (!IS_ERR(esai->extalclk)) + clk_disable_unprepare(esai->extalclk); + if (!IS_ERR(esai->spbaclk)) + clk_disable_unprepare(esai->spbaclk); + clk_disable_unprepare(esai->coreclk); + + return 0; } -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_esai_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fsl_esai_suspend, fsl_esai_resume) + SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend, + fsl_esai_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver fsl_esai_driver = { .probe = fsl_esai_probe, + .remove = fsl_esai_remove, .driver = { .name = "fsl-esai-dai", .pm = &fsl_esai_pm_ops, diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 8593269156bd..d58cc3ae90d8 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -596,15 +596,8 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct device *dev = &sai->pdev->dev; int ret; - ret = clk_prepare_enable(sai->bus_clk); - if (ret) { - dev_err(dev, "failed to enable bus clock: %d\n", ret); - return ret; - } - regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, FSL_SAI_CR3_TRCE); @@ -621,8 +614,6 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream, bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0); - - clk_disable_unprepare(sai->bus_clk); } static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { @@ -935,6 +926,14 @@ static int fsl_sai_runtime_suspend(struct device *dev) { struct fsl_sai *sai = dev_get_drvdata(dev); + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]); + + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]); + + clk_disable_unprepare(sai->bus_clk); + regcache_cache_only(sai->regmap, true); regcache_mark_dirty(sai->regmap); @@ -944,6 +943,25 @@ static int fsl_sai_runtime_suspend(struct device *dev) static int fsl_sai_runtime_resume(struct device *dev) { struct fsl_sai *sai = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(sai->bus_clk); + if (ret) { + dev_err(dev, "failed to enable bus clock: %d\n", ret); + return ret; + } + + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) { + ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[1]]); + if (ret) + goto disable_bus_clk; + } + + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) { + ret = clk_prepare_enable(sai->mclk_clk[sai->mclk_id[0]]); + if (ret) + goto disable_tx_clk; + } regcache_cache_only(sai->regmap, false); regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); @@ -951,7 +969,23 @@ static int fsl_sai_runtime_resume(struct device *dev) usleep_range(1000, 2000); regmap_write(sai->regmap, FSL_SAI_TCSR, 0); regmap_write(sai->regmap, FSL_SAI_RCSR, 0); - return regcache_sync(sai->regmap); + + ret = regcache_sync(sai->regmap); + if (ret) + goto disable_rx_clk; + + return 0; + +disable_rx_clk: + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]); +disable_tx_clk: + if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_PLAYBACK)) + clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[1]]); +disable_bus_clk: + clk_disable_unprepare(sai->bus_clk); + + return ret; } #endif /* CONFIG_PM */ diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 09b2967befd9..fa862af25c1a 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1582,9 +1582,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) } } - ret = fsl_ssi_debugfs_create(&ssi->dbg_stats, dev); - if (ret) - goto error_asoc_register; + fsl_ssi_debugfs_create(&ssi->dbg_stats, dev); /* Initially configures SSI registers */ fsl_ssi_hw_init(ssi); diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h index 0bdda608d414..db57cad80449 100644 --- a/sound/soc/fsl/fsl_ssi.h +++ b/sound/soc/fsl/fsl_ssi.h @@ -270,7 +270,6 @@ struct device; struct fsl_ssi_dbg { struct dentry *dbg_dir; - struct dentry *dbg_stats; struct { unsigned int rfrc; @@ -299,7 +298,7 @@ struct fsl_ssi_dbg { void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *ssi_dbg, u32 sisr); -int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev); +void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev); void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg); @@ -312,10 +311,9 @@ static inline void fsl_ssi_dbg_isr(struct fsl_ssi_dbg *stats, u32 sisr) { } -static inline int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, - struct device *dev) +static inline void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, + struct device *dev) { - return 0; } static inline void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) diff --git a/sound/soc/fsl/fsl_ssi_dbg.c b/sound/soc/fsl/fsl_ssi_dbg.c index 6f6294149476..2a20ee23dc52 100644 --- a/sound/soc/fsl/fsl_ssi_dbg.c +++ b/sound/soc/fsl/fsl_ssi_dbg.c @@ -126,25 +126,15 @@ static int fsl_ssi_stats_show(struct seq_file *s, void *unused) DEFINE_SHOW_ATTRIBUTE(fsl_ssi_stats); -int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev) +void fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev) { ssi_dbg->dbg_dir = debugfs_create_dir(dev_name(dev), NULL); - if (!ssi_dbg->dbg_dir) - return -ENOMEM; - ssi_dbg->dbg_stats = debugfs_create_file("stats", 0444, - ssi_dbg->dbg_dir, ssi_dbg, - &fsl_ssi_stats_fops); - if (!ssi_dbg->dbg_stats) { - debugfs_remove(ssi_dbg->dbg_dir); - return -ENOMEM; - } - - return 0; + debugfs_create_file("stats", 0444, ssi_dbg->dbg_dir, ssi_dbg, + &fsl_ssi_stats_fops); } void fsl_ssi_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) { - debugfs_remove(ssi_dbg->dbg_stats); - debugfs_remove(ssi_dbg->dbg_dir); + debugfs_remove_recursive(ssi_dbg->dbg_dir); } diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index 040d06b89f00..9bab202569af 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c @@ -57,7 +57,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, of_node_put(dma_channel_np); return ret; } - snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%pOFn", + snprintf((char *)dai->platforms->name, DAI_NAME_SIZE, "%llx.%pOFn", (unsigned long long) res.start, dma_channel_np); iprop = of_get_property(dma_channel_np, "cell-index", NULL); diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 9aaf3e5b45b9..9e1cb18859ce 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -205,6 +205,15 @@ static int imx_audmix_probe(struct platform_device *pdev) return -ENOMEM; for (i = 0; i < num_dai; i++) { + struct snd_soc_dai_link_component *dlc; + + /* for CPU/Codec/Platform x 2 */ + dlc = devm_kzalloc(&pdev->dev, 6 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) { + dev_err(&pdev->dev, "failed to allocate dai_link\n"); + return -ENOMEM; + } + ret = of_parse_phandle_with_args(audmix_np, "dais", NULL, i, &args); if (ret < 0) { @@ -231,13 +240,21 @@ static int imx_audmix_probe(struct platform_device *pdev) dai_name, "CPU-Capture"); } + priv->dai[i].cpus = &dlc[0]; + priv->dai[i].codecs = &dlc[1]; + priv->dai[i].platforms = &dlc[2]; + + priv->dai[i].num_cpus = 1; + priv->dai[i].num_codecs = 1; + priv->dai[i].num_platforms = 1; + priv->dai[i].name = dai_name; priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; - priv->dai[i].codec_dai_name = "snd-soc-dummy-dai"; - priv->dai[i].codec_name = "snd-soc-dummy"; - priv->dai[i].cpu_of_node = args.np; - priv->dai[i].cpu_dai_name = dev_name(&cpu_pdev->dev); - priv->dai[i].platform_of_node = args.np; + priv->dai[i].codecs->dai_name = "snd-soc-dummy-dai"; + priv->dai[i].codecs->name = "snd-soc-dummy"; + priv->dai[i].cpus->of_node = args.np; + priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); + priv->dai[i].platforms->of_node = args.np; priv->dai[i].dynamic = 1; priv->dai[i].dpcm_playback = 1; priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); @@ -252,12 +269,20 @@ static int imx_audmix_probe(struct platform_device *pdev) be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, "AUDMIX-Capture-%d", i); + priv->dai[num_dai + i].cpus = &dlc[3]; + priv->dai[num_dai + i].codecs = &dlc[4]; + priv->dai[num_dai + i].platforms = &dlc[5]; + + priv->dai[num_dai + i].num_cpus = 1; + priv->dai[num_dai + i].num_codecs = 1; + priv->dai[num_dai + i].num_platforms = 1; + priv->dai[num_dai + i].name = be_name; - priv->dai[num_dai + i].codec_dai_name = "snd-soc-dummy-dai"; - priv->dai[num_dai + i].codec_name = "snd-soc-dummy"; - priv->dai[num_dai + i].cpu_of_node = audmix_np; - priv->dai[num_dai + i].cpu_dai_name = be_name; - priv->dai[num_dai + i].platform_name = "snd-soc-dummy"; + priv->dai[num_dai + i].codecs->dai_name = "snd-soc-dummy-dai"; + priv->dai[num_dai + i].codecs->name = "snd-soc-dummy"; + priv->dai[num_dai + i].cpus->of_node = audmix_np; + priv->dai[num_dai + i].cpus->dai_name = be_name; + priv->dai[num_dai + i].platforms->name = "snd-soc-dummy"; priv->dai[num_dai + i].no_pcm = 1; priv->dai[num_dai + i].dpcm_playback = 1; priv->dai[num_dai + i].dpcm_capture = 1; diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index 04e59e66711d..b2351cd33b0f 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -141,17 +141,11 @@ static void audmux_debugfs_init(void) char buf[20]; audmux_debugfs_root = debugfs_create_dir("audmux", NULL); - if (!audmux_debugfs_root) { - pr_warning("Failed to create AUDMUX debugfs root\n"); - return; - } for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) { snprintf(buf, sizeof(buf), "ssi%lu", i); - if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, - (void *)i, &audmux_debugfs_fops)) - pr_warning("Failed to create AUDMUX port %lu debugfs file\n", - i); + debugfs_create_file(buf, 0444, audmux_debugfs_root, + (void *)i, &audmux_debugfs_fops); } } diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index c9d8739b04a9..15a27a2cd0ca 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -74,6 +74,7 @@ static int imx_es8328_probe(struct platform_device *pdev) struct device_node *ssi_np = NULL, *codec_np = NULL; struct platform_device *ssi_pdev; struct imx_es8328_data *data; + struct snd_soc_dai_link_component *comp; u32 int_port, ext_port; int ret; struct device *dev = &pdev->dev; @@ -147,16 +148,30 @@ static int imx_es8328_probe(struct platform_device *pdev) goto fail; } + comp = devm_kzalloc(dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto fail; + } + data->dev = dev; data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); + data->dai.cpus = &comp[0]; + data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; + + data->dai.num_cpus = 1; + data->dai.num_codecs = 1; + data->dai.num_platforms = 1; + data->dai.name = "hifi"; data->dai.stream_name = "hifi"; - data->dai.codec_dai_name = "es8328-hifi-analog"; - data->dai.codec_of_node = codec_np; - data->dai.cpu_of_node = ssi_np; - data->dai.platform_of_node = ssi_np; + data->dai.codecs->dai_name = "es8328-hifi-analog"; + data->dai.codecs->of_node = codec_np; + data->dai.cpus->of_node = ssi_np; + data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_es8328_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c index 545815a27074..2b679680c93f 100644 --- a/sound/soc/fsl/imx-mc13783.c +++ b/sound/soc/fsl/imx-mc13783.c @@ -46,17 +46,19 @@ static const struct snd_soc_ops imx_mc13783_hifi_ops = { .hw_params = imx_mc13783_hifi_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("mc13783-codec", "mc13783-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link imx_mc13783_dai_mc13783[] = { { .name = "MC13783", .stream_name = "Sound", - .codec_dai_name = "mc13783-hifi", - .codec_name = "mc13783-codec", - .cpu_dai_name = "imx-ssi.0", - .platform_name = "imx-ssi.0", .ops = &imx_mc13783_hifi_ops, .symmetric_rates = 1, .dai_fmt = FMT_SSI, + SND_SOC_DAILINK_REG(hifi), }, }; diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 314814ddd2b0..04a9bc749016 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * imx-pcm-dma-mx2.c -- ALSA Soc Audio Layer * @@ -5,11 +6,6 @@ * * This code is based on code copyrighted by Freescale, * Liam Girdwood, Javier Martin and probably others. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. */ #include <linux/platform_device.h> #include <linux/dmaengine.h> diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index bf8597f57dce..15e8b9343c35 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -55,6 +55,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) struct platform_device *ssi_pdev; struct i2c_client *codec_dev; struct imx_sgtl5000_data *data = NULL; + struct snd_soc_dai_link_component *comp; int int_port, ext_port; int ret; @@ -122,6 +123,12 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) goto fail; } + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto fail; + } + data->codec_clk = clk_get(&codec_dev->dev, NULL); if (IS_ERR(data->codec_clk)) { ret = PTR_ERR(data->codec_clk); @@ -130,12 +137,20 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) data->clk_frequency = clk_get_rate(data->codec_clk); + data->dai.cpus = &comp[0]; + data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; + + data->dai.num_cpus = 1; + data->dai.num_codecs = 1; + data->dai.num_platforms = 1; + data->dai.name = "HiFi"; data->dai.stream_name = "HiFi"; - data->dai.codec_dai_name = "sgtl5000"; - data->dai.codec_of_node = codec_np; - data->dai.cpu_of_node = ssi_np; - data->dai.platform_of_node = ssi_np; + data->dai.codecs->dai_name = "sgtl5000"; + data->dai.codecs->of_node = codec_np; + data->dai.cpus->of_node = ssi_np; + data->dai.platforms->of_node = ssi_np; data->dai.init = &imx_sgtl5000_dai_init; data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c index 4f7f210beb18..6c4dadf60355 100644 --- a/sound/soc/fsl/imx-spdif.c +++ b/sound/soc/fsl/imx-spdif.c @@ -15,6 +15,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) { struct device_node *spdif_np, *np = pdev->dev.of_node; struct imx_spdif_data *data; + struct snd_soc_dai_link_component *comp; int ret = 0; spdif_np = of_parse_phandle(np, "spdif-controller", 0); @@ -25,17 +26,26 @@ static int imx_spdif_audio_probe(struct platform_device *pdev) } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) { + comp = devm_kzalloc(&pdev->dev, 3 * sizeof(*comp), GFP_KERNEL); + if (!data || !comp) { ret = -ENOMEM; goto end; } + data->dai.cpus = &comp[0]; + data->dai.codecs = &comp[1]; + data->dai.platforms = &comp[2]; + + data->dai.num_cpus = 1; + data->dai.num_codecs = 1; + data->dai.num_platforms = 1; + data->dai.name = "S/PDIF PCM"; data->dai.stream_name = "S/PDIF PCM"; - data->dai.codec_dai_name = "snd-soc-dummy-dai"; - data->dai.codec_name = "snd-soc-dummy"; - data->dai.cpu_of_node = spdif_np; - data->dai.platform_of_node = spdif_np; + data->dai.codecs->dai_name = "snd-soc-dummy-dai"; + data->dai.codecs->name = "snd-soc-dummy"; + data->dai.cpus->of_node = spdif_np; + data->dai.platforms->of_node = spdif_np; data->dai.playback_only = true; data->dai.capture_only = true; diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index f6261a3eeb0f..23617eb09ba1 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -189,6 +189,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; struct mpc8610_hpcd_data *machine_data; + struct snd_soc_dai_link_component *comp; int ret = -ENODEV; const char *sprop; const u32 *iprop; @@ -206,14 +207,36 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) goto error_alloc; } - machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + comp = devm_kzalloc(&pdev->dev, 6 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto error_alloc; + } + + machine_data->dai[0].cpus = &comp[0]; + machine_data->dai[0].codecs = &comp[1]; + machine_data->dai[0].platforms = &comp[2]; + + machine_data->dai[0].num_cpus = 1; + machine_data->dai[0].num_codecs = 1; + machine_data->dai[0].num_platforms = 1; + + machine_data->dai[1].cpus = &comp[3]; + machine_data->dai[1].codecs = &comp[4]; + machine_data->dai[1].platforms = &comp[5]; + + machine_data->dai[1].num_cpus = 1; + machine_data->dai[1].num_codecs = 1; + machine_data->dai[1].num_platforms = 1; + + machine_data->dai[0].cpus->dai_name = dev_name(&ssi_pdev->dev); machine_data->dai[0].ops = &mpc8610_hpcd_ops; /* ASoC core can match codec with device node */ - machine_data->dai[0].codec_of_node = codec_np; + machine_data->dai[0].codecs->of_node = codec_np; /* The DAI name from the codec (snd_soc_dai_driver.name) */ - machine_data->dai[0].codec_dai_name = "cs4270-hifi"; + machine_data->dai[0].codecs->dai_name = "cs4270-hifi"; /* We register two DAIs per SSI, one for playback and the other for * capture. Currently, we only support codecs that have one DAI for @@ -306,7 +329,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } /* Find the playback DMA channel to use. */ - machine_data->dai[0].platform_name = machine_data->platform_name[0]; + machine_data->dai[0].platforms->name = machine_data->platform_name[0]; ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0], &machine_data->dma_channel_id[0], @@ -317,7 +340,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } /* Find the capture DMA channel to use. */ - machine_data->dai[1].platform_name = machine_data->platform_name[1]; + machine_data->dai[1].platforms->name = machine_data->platform_name[1]; ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1], &machine_data->dma_channel_id[1], diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index 37a4520aef62..38ac4a397742 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c @@ -132,16 +132,19 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { {"IN3_L", NULL, "Mic Bias"}, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic32x4.0-0018", + "tlv320aic32x4-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link mx27vis_aic32x4_dai = { .name = "tlv320aic32x4", .stream_name = "TLV320AIC32X4", - .codec_dai_name = "tlv320aic32x4-hifi", - .platform_name = "imx-ssi.0", - .codec_name = "tlv320aic32x4.0-0018", - .cpu_dai_name = "imx-ssi.0", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .ops = &mx27vis_aic32x4_snd_ops, + SND_SOC_DAILINK_REG(hifi), }; static struct snd_soc_card mx27vis_aic32x4 = { diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 80384f70878d..6114b01b90f7 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -199,6 +199,7 @@ static int p1022_ds_probe(struct platform_device *pdev) struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; struct machine_data *mdata; + struct snd_soc_dai_link_component *comp; int ret = -ENODEV; const char *sprop; const u32 *iprop; @@ -216,11 +217,34 @@ static int p1022_ds_probe(struct platform_device *pdev) goto error_put; } - mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + comp = devm_kzalloc(&pdev->dev, 6 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto error_put; + } + + mdata->dai[0].cpus = &comp[0]; + mdata->dai[0].codecs = &comp[1]; + mdata->dai[0].platforms = &comp[2]; + + mdata->dai[0].num_cpus = 1; + mdata->dai[0].num_codecs = 1; + mdata->dai[0].num_platforms = 1; + + mdata->dai[1].cpus = &comp[3]; + mdata->dai[1].codecs = &comp[4]; + mdata->dai[1].platforms = &comp[5]; + + mdata->dai[1].num_cpus = 1; + mdata->dai[1].num_codecs = 1; + mdata->dai[1].num_platforms = 1; + + + mdata->dai[0].cpus->dai_name = dev_name(&ssi_pdev->dev); mdata->dai[0].ops = &p1022_ds_ops; /* ASoC core can match codec with device node */ - mdata->dai[0].codec_of_node = codec_np; + mdata->dai[0].codecs->of_node = codec_np; /* We register two DAIs per SSI, one for playback and the other for * capture. We support codecs that have separate DAIs for both playback @@ -229,8 +253,8 @@ static int p1022_ds_probe(struct platform_device *pdev) memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link)); /* The DAI names from the codec (snd_soc_dai_driver.name) */ - mdata->dai[0].codec_dai_name = "wm8776-hifi-playback"; - mdata->dai[1].codec_dai_name = "wm8776-hifi-capture"; + mdata->dai[0].codecs->dai_name = "wm8776-hifi-playback"; + mdata->dai[1].codecs->dai_name = "wm8776-hifi-capture"; /* Get the device ID */ iprop = of_get_property(np, "cell-index", NULL); @@ -316,7 +340,7 @@ static int p1022_ds_probe(struct platform_device *pdev) } /* Find the playback DMA channel to use. */ - mdata->dai[0].platform_name = mdata->platform_name[0]; + mdata->dai[0].platforms->name = mdata->platform_name[0]; ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], &mdata->dma_channel_id[0], &mdata->dma_id[0]); @@ -326,7 +350,7 @@ static int p1022_ds_probe(struct platform_device *pdev) } /* Find the capture DMA channel to use. */ - mdata->dai[1].platform_name = mdata->platform_name[1]; + mdata->dai[1].platforms->name = mdata->platform_name[1]; ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], &mdata->dma_channel_id[1], &mdata->dma_id[1]); diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c index 1c32c2d8c6b0..72687235c0ae 100644 --- a/sound/soc/fsl/p1022_rdk.c +++ b/sound/soc/fsl/p1022_rdk.c @@ -203,6 +203,7 @@ static int p1022_rdk_probe(struct platform_device *pdev) struct device_node *np = ssi_pdev->dev.of_node; struct device_node *codec_np = NULL; struct machine_data *mdata; + struct snd_soc_dai_link_component *comp; const u32 *iprop; int ret; @@ -219,11 +220,33 @@ static int p1022_rdk_probe(struct platform_device *pdev) goto error_put; } - mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + comp = devm_kzalloc(&pdev->dev, 6 * sizeof(*comp), GFP_KERNEL); + if (!comp) { + ret = -ENOMEM; + goto error_put; + } + + mdata->dai[0].cpus = &comp[0]; + mdata->dai[0].codecs = &comp[1]; + mdata->dai[0].platforms = &comp[2]; + + mdata->dai[0].num_cpus = 1; + mdata->dai[0].num_codecs = 1; + mdata->dai[0].num_platforms = 1; + + mdata->dai[1].cpus = &comp[3]; + mdata->dai[1].codecs = &comp[4]; + mdata->dai[1].platforms = &comp[5]; + + mdata->dai[1].num_cpus = 1; + mdata->dai[1].num_codecs = 1; + mdata->dai[1].num_platforms = 1; + + mdata->dai[0].cpus->dai_name = dev_name(&ssi_pdev->dev); mdata->dai[0].ops = &p1022_rdk_ops; /* ASoC core can match codec with device node */ - mdata->dai[0].codec_of_node = codec_np; + mdata->dai[0].codecs->of_node = codec_np; /* * We register two DAIs per SSI, one for playback and the other for @@ -233,8 +256,8 @@ static int p1022_rdk_probe(struct platform_device *pdev) memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link)); /* The DAI names from the codec (snd_soc_dai_driver.name) */ - mdata->dai[0].codec_dai_name = "wm8960-hifi"; - mdata->dai[1].codec_dai_name = mdata->dai[0].codec_dai_name; + mdata->dai[0].codecs->dai_name = "wm8960-hifi"; + mdata->dai[1].codecs->dai_name = mdata->dai[0].codecs->dai_name; /* * Configure the SSI for I2S slave mode. Older device trees have @@ -266,7 +289,7 @@ static int p1022_rdk_probe(struct platform_device *pdev) } /* Find the playback DMA channel to use. */ - mdata->dai[0].platform_name = mdata->platform_name[0]; + mdata->dai[0].platforms->name = mdata->platform_name[0]; ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], &mdata->dma_channel_id[0], &mdata->dma_id[0]); @@ -277,7 +300,7 @@ static int p1022_rdk_probe(struct platform_device *pdev) } /* Find the capture DMA channel to use. */ - mdata->dai[1].platform_name = mdata->platform_name[1]; + mdata->dai[1].platforms->name = mdata->platform_name[1]; ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], &mdata->dma_channel_id[1], &mdata->dma_id[1]); diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index a7fe4ad25c52..af3c3b90c0ac 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -23,20 +23,26 @@ struct pcm030_audio_data { struct platform_device *codec_device; }; +SND_SOC_DAILINK_DEFS(analog, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(iec958, + DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + static struct snd_soc_dai_link pcm030_fabric_dai[] = { { .name = "AC97.0", .stream_name = "AC97 Analog", - .codec_dai_name = "wm9712-hifi", - .cpu_dai_name = "mpc5200-psc-ac97.0", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(analog), }, { .name = "AC97.1", .stream_name = "AC97 IEC958", - .codec_dai_name = "wm9712-aux", - .cpu_dai_name = "mpc5200-psc-ac97.1", - .codec_name = "wm9712-codec", + SND_SOC_DAILINK_REG(iec958), }, }; @@ -76,7 +82,7 @@ static int pcm030_fabric_probe(struct platform_device *op) } for_each_card_prelinks(card, i, dai_link) - dai_link->platform_of_node = platform_np; + dai_link->platforms->of_node = platform_np; ret = request_module("snd-soc-wm9712"); if (ret) diff --git a/sound/soc/fsl/phycore-ac97.c b/sound/soc/fsl/phycore-ac97.c index fe7ba6db7c96..e561f7ff1699 100644 --- a/sound/soc/fsl/phycore-ac97.c +++ b/sound/soc/fsl/phycore-ac97.c @@ -20,15 +20,17 @@ static struct snd_soc_card imx_phycore; static const struct snd_soc_ops imx_phycore_hifi_ops = { }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { { .name = "HiFi", .stream_name = "HiFi", - .codec_dai_name = "wm9712-hifi", - .codec_name = "wm9712-codec", - .cpu_dai_name = "imx-ssi.0", - .platform_name = "imx-ssi.0", .ops = &imx_phycore_hifi_ops, + SND_SOC_DAILINK_REG(hifi), }, }; diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index aad24ccbef90..52d321bede9c 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c @@ -216,18 +216,20 @@ static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) } +SND_SOC_DAILINK_DEFS(ev1, + DAILINK_COMP_ARRAY(COMP_CPU("imx-ssi.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("wm8350-codec.0-0x1a", "wm8350-hifi")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("imx-ssi.0"))); + static struct snd_soc_dai_link wm1133_ev1_dai = { .name = "WM1133-EV1", .stream_name = "Audio", - .cpu_dai_name = "imx-ssi.0", - .codec_dai_name = "wm8350-hifi", - .platform_name = "imx-ssi.0", - .codec_name = "wm8350-codec.0-0x1a", .init = wm1133_ev1_init, .ops = &wm1133_ev1_ops, .symmetric_rates = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAILINK_REG(ev1), }; static struct snd_soc_card wm1133_ev1 = { |