Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
[deliverable/linux.git] / sound / soc / intel / skylake / skl-pcm.c
index b6e6b61d10ec22349650ee5c1db3074068a180e4..7c81b31748ffcba2ab7c5d8a8961eb83d4134f55 100644 (file)
@@ -51,7 +51,7 @@ static struct snd_pcm_hardware azx_pcm_hw = {
        .rate_min =             8000,
        .rate_max =             48000,
        .channels_min =         1,
-       .channels_max =         HDA_QUAD,
+       .channels_max =         8,
        .buffer_bytes_max =     AZX_MAX_BUF_SIZE,
        .period_bytes_min =     128,
        .period_bytes_max =     AZX_MAX_BUF_SIZE / 2,
@@ -206,6 +206,23 @@ static int skl_get_format(struct snd_pcm_substream *substream,
        return format_val;
 }
 
+static int skl_be_prepare(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct skl *skl = get_skl_ctx(dai->dev);
+       struct skl_sst *ctx = skl->skl_sst;
+       struct skl_module_cfg *mconfig;
+
+       if (dai->playback_widget->power || dai->capture_widget->power)
+               return 0;
+
+       mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
+       if (mconfig == NULL)
+               return -EINVAL;
+
+       return skl_dsp_set_dma_control(ctx, mconfig);
+}
+
 static int skl_pcm_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -385,23 +402,33 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
        struct skl_module_cfg *mconfig;
        struct hdac_ext_bus *ebus = get_bus_ctx(substream);
        struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
+       struct snd_soc_dapm_widget *w;
        int ret;
 
        mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
        if (!mconfig)
                return -EIO;
 
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               w = dai->playback_widget;
+       else
+               w = dai->capture_widget;
+
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
-               skl_pcm_prepare(substream, dai);
-               /*
-                * enable DMA Resume enable bit for the stream, set the dpib
-                * & lpib position to resune before starting the DMA
-                */
-               snd_hdac_ext_stream_drsm_enable(ebus, true,
-                                       hdac_stream(stream)->index);
-               snd_hdac_ext_stream_set_dpibr(ebus, stream, stream->dpib);
-               snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
+               if (!w->ignore_suspend) {
+                       skl_pcm_prepare(substream, dai);
+                       /*
+                        * enable DMA Resume enable bit for the stream, set the
+                        * dpib & lpib position to resume before starting the
+                        * DMA
+                        */
+                       snd_hdac_ext_stream_drsm_enable(ebus, true,
+                                               hdac_stream(stream)->index);
+                       snd_hdac_ext_stream_set_dpibr(ebus, stream,
+                                                       stream->dpib);
+                       snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
+               }
 
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -431,7 +458,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
                        return ret;
 
                ret = skl_decoupled_trigger(substream, cmd);
-               if (cmd == SNDRV_PCM_TRIGGER_SUSPEND) {
+               if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) {
                        /* save the dpib and lpib positions */
                        stream->dpib = readl(ebus->bus.remap_addr +
                                        AZX_REG_VS_SDXDPIB_XBASE +
@@ -458,7 +485,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
        struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
        struct hdac_ext_stream *link_dev;
        struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct skl_dma_params *dma_params;
+       struct hdac_ext_dma_params *dma_params;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct skl_pipe_params p_params = {0};
 
@@ -470,11 +497,9 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
        snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
 
        /* set the stream tag in the codec dai dma params  */
-       dma_params = (struct skl_dma_params *)
-                       snd_soc_dai_get_dma_data(codec_dai, substream);
+       dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
        if (dma_params)
                dma_params->stream_tag =  hdac_stream(link_dev)->stream_tag;
-       snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params);
 
        p_params.s_fmt = snd_pcm_format_width(params_format(params));
        p_params.ch = params_channels(params);
@@ -508,7 +533,6 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
        if (!link)
                return -EINVAL;
 
-       snd_hdac_ext_bus_link_power_up(link);
        snd_hdac_ext_link_stream_reset(link_dev);
 
        snd_hdac_ext_link_stream_setup(link_dev, format_val);
@@ -588,6 +612,7 @@ static struct snd_soc_dai_ops skl_dmic_dai_ops = {
 
 static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
        .hw_params = skl_be_hw_params,
+       .prepare = skl_be_prepare,
 };
 
 static struct snd_soc_dai_ops skl_link_dai_ops = {
@@ -660,6 +685,51 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
        },
 },
+{
+       .name = "HDMI1 Pin",
+       .ops = &skl_pcm_dai_ops,
+       .playback = {
+               .stream_name = "HDMI1 Playback",
+               .channels_min = HDA_STEREO,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                       SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+                       SNDRV_PCM_FMTBIT_S32_LE,
+       },
+},
+{
+       .name = "HDMI2 Pin",
+       .ops = &skl_pcm_dai_ops,
+       .playback = {
+               .stream_name = "HDMI2 Playback",
+               .channels_min = HDA_STEREO,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                       SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+                       SNDRV_PCM_FMTBIT_S32_LE,
+       },
+},
+{
+       .name = "HDMI3 Pin",
+       .ops = &skl_pcm_dai_ops,
+       .playback = {
+               .stream_name = "HDMI3 Playback",
+               .channels_min = HDA_STEREO,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                       SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+                       SNDRV_PCM_FMTBIT_S32_LE,
+       },
+},
 
 /* BE CPU  Dais */
 {
@@ -699,16 +769,115 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
        },
 },
 {
-       .name = "iDisp Pin",
-       .ops = &skl_link_dai_ops,
+       .name = "SSP2 Pin",
+       .ops = &skl_be_ssp_dai_ops,
        .playback = {
-               .stream_name = "iDisp Tx",
+               .stream_name = "ssp2 Tx",
                .channels_min = HDA_STEREO,
                .channels_max = HDA_STEREO,
-               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "ssp2 Rx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+{
+       .name = "SSP3 Pin",
+       .ops = &skl_be_ssp_dai_ops,
+       .playback = {
+               .stream_name = "ssp3 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "ssp3 Rx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+{
+       .name = "SSP4 Pin",
+       .ops = &skl_be_ssp_dai_ops,
+       .playback = {
+               .stream_name = "ssp4 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "ssp4 Rx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+},
+{
+       .name = "SSP5 Pin",
+       .ops = &skl_be_ssp_dai_ops,
+       .playback = {
+               .stream_name = "ssp5 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "ssp5 Rx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_48000,
                .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
 },
+{
+       .name = "iDisp1 Pin",
+       .ops = &skl_link_dai_ops,
+       .playback = {
+               .stream_name = "iDisp1 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE,
+       },
+},
+{
+       .name = "iDisp2 Pin",
+       .ops = &skl_link_dai_ops,
+       .playback = {
+               .stream_name = "iDisp2 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
+                       SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE,
+       },
+},
+{
+       .name = "iDisp3 Pin",
+       .ops = &skl_link_dai_ops,
+       .playback = {
+               .stream_name = "iDisp3 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
+                       SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE,
+       },
+},
 {
        .name = "DMIC01 Pin",
        .ops = &skl_dmic_dai_ops,
@@ -863,7 +1032,9 @@ static int skl_get_delay_from_lpib(struct hdac_ext_bus *ebus,
                else
                        delay += hstream->bufsize;
        }
-       delay = (hstream->bufsize == delay) ? 0 : delay;
+
+       if (hstream->bufsize == delay)
+               delay = 0;
 
        if (delay >= hstream->period_bytes) {
                dev_info(bus->dev,
This page took 0.041136 seconds and 5 git commands to generate.