diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 198d37d04d78..b56a4435439a 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -987,6 +987,8 @@ int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
 			struct snd_pcm_hw_rule *rule);
 
 int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
+int constrain_params_by_rules(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *params);
 
 int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
 				 u_int64_t mask);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index d6f14162bce5..2ff6e182c7f5 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -22,6 +22,7 @@
 #include <sound/pcm_params.h>
 #include <sound/timer.h>
 #include <sound/minors.h>
+#include <sound/soc.h>
 #include <linux/uio.h>
 #include <linux/delay.h>
 
@@ -326,11 +327,10 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-static int constrain_params_by_rules(struct snd_pcm_substream *substream,
-				     struct snd_pcm_hw_params *params)
+int constrain_params_by_rules(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *params)
 {
-	struct snd_pcm_hw_constraints *constrs =
-					&substream->runtime->hw_constraints;
+	struct snd_pcm_hw_constraints *constrs;
 	unsigned int k;
 	unsigned int *rstamps;
 	unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
@@ -342,6 +342,14 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
 	bool again;
 	int changed, err = 0;
 
+	if (substream->pcm->internal) {
+		struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+
+		constrs = &rtd->dpcm[substream->stream].hw_constraints;
+	} else {
+		constrs = &substream->runtime->hw_constraints;
+	}
+
 	/*
 	 * Each application of rule has own sequence number.
 	 *
@@ -446,6 +454,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
 	kfree(rstamps);
 	return err;
 }
+EXPORT_SYMBOL(constrain_params_by_rules);
 
 static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
 				     struct snd_pcm_hw_params *params)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index dae246918e0d..5bd71d48c0de 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1934,11 +1934,25 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
 		memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params,
 				sizeof(struct snd_pcm_hw_params));
 
+		/* copy FE mask and interval constraints */
+		memcpy(&be->dpcm[stream].hw_constraints.masks,
+		       &be_substream->runtime->hw_constraints.masks,
+		       sizeof(be_substream->runtime->hw_constraints.masks));
+		memcpy(&be->dpcm[stream].hw_constraints.intervals,
+		       &be_substream->runtime->hw_constraints.intervals,
+		       sizeof(be_substream->runtime->hw_constraints.intervals));
+
 		/* perform any hw_params fixups */
 		ret = snd_soc_link_be_hw_params_fixup(be, &dpcm->hw_params);
 		if (ret < 0)
 			goto unwind;
 
+		/* apply constrain rules */
+		dpcm->hw_params.rmask = ~0U;
+		ret = constrain_params_by_rules(be_substream, &dpcm->hw_params);
+		if (ret < 0)
+			goto unwind;
+
 		/* copy the fixed-up hw params for BE dai */
 		memcpy(&be->dpcm[stream].hw_params, &dpcm->hw_params,
 		       sizeof(struct snd_pcm_hw_params));
@@ -2002,6 +2016,22 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
 
 	memcpy(&fe->dpcm[stream].hw_params, params,
 			sizeof(struct snd_pcm_hw_params));
+	if (!fe->dai_link->dpcm_merged_format) {
+		snd_mask_any(hw_param_mask(&fe->dpcm[stream].hw_params,
+					   SNDRV_PCM_HW_PARAM_FORMAT));
+		snd_interval_any(hw_param_interval(&fe->dpcm[stream].hw_params,
+						   SNDRV_PCM_HW_PARAM_SAMPLE_BITS));
+		snd_interval_any(hw_param_interval(&fe->dpcm[stream].hw_params,
+						   SNDRV_PCM_HW_PARAM_FRAME_BITS));
+	}
+	if (!fe->dai_link->dpcm_merged_chan) {
+		snd_interval_any(hw_param_interval(&fe->dpcm[stream].hw_params,
+						   SNDRV_PCM_HW_PARAM_CHANNELS));
+	}
+	if (!fe->dai_link->dpcm_merged_rate) {
+		snd_interval_any(hw_param_interval(&fe->dpcm[stream].hw_params,
+						   SNDRV_PCM_HW_PARAM_RATE));
+	}
 	ret = dpcm_be_dai_hw_params(fe, stream);
 	if (ret < 0)
 		goto out;
