}
 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
 
-/* this may get called several times by oss emulation */
+static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream,
+                               struct snd_sof_dev *sdev,
+                               struct snd_sof_pcm *spcm)
+{
+       struct sof_ipc_stream stream;
+       struct sof_ipc_reply reply;
+       int ret;
+
+       stream.hdr.size = sizeof(stream);
+       stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
+       stream.comp_id = spcm->stream[substream->stream].comp_id;
+
+       /* send IPC to the DSP */
+       ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
+                                sizeof(stream), &reply, sizeof(reply));
+       if (!ret)
+               spcm->prepared[substream->stream] = false;
+
+       return ret;
+}
+
 static int sof_pcm_hw_params(struct snd_soc_component *component,
                             struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
        if (!spcm)
                return -EINVAL;
 
+       /*
+        * Handle repeated calls to hw_params() without free_pcm() in
+        * between. At least ALSA OSS emulation depends on this.
+        */
+       if (spcm->prepared[substream->stream]) {
+               ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
+               if (ret < 0)
+                       return ret;
+       }
+
        dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n",
                spcm->pcm.pcm_id, substream->stream);
 
        return ret;
 }
 
-static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream,
-                               struct snd_sof_dev *sdev,
-                               struct snd_sof_pcm *spcm)
-{
-       struct sof_ipc_stream stream;
-       struct sof_ipc_reply reply;
-       int ret;
-
-       stream.hdr.size = sizeof(stream);
-       stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
-       stream.comp_id = spcm->stream[substream->stream].comp_id;
-
-       /* send IPC to the DSP */
-       ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
-                                sizeof(stream), &reply, sizeof(reply));
-       if (!ret)
-               spcm->prepared[substream->stream] = false;
-
-       return ret;
-}
-
 static int sof_pcm_hw_free(struct snd_soc_component *component,
                           struct snd_pcm_substream *substream)
 {