lkml.org 
[lkml]   [2016]   [Oct]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.4 071/125] ALSA: rme96: Fix unexpected volume reset after rate changes
    Date
    From: Takashi Iwai <tiwai@suse.de>

    3.4.113-rc1 review patch. If anyone has any objections, please let me know.

    ------------------


    commit a74a821624c0c75388a193337babd17a8c02c740 upstream.

    rme96 driver needs to reset DAC depending on the sample rate, and this
    results in resetting to the max volume suddenly. It's because of the
    missing call of snd_rme96_apply_dac_volume().

    However, calling this function right after the DAC reset still may not
    work, and we need some delay before this call. Since the DAC reset
    and the procedure after that are performed in the spinlock, we delay
    the DAC volume restore at the end after the spinlock.

    Reported-and-tested-by: Sylvain LABOISNE <maeda1@free.fr>
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Zefan Li <lizefan@huawei.com>
    ---
    sound/pci/rme96.c | 41 ++++++++++++++++++++++++++---------------
    1 file changed, 26 insertions(+), 15 deletions(-)

    diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
    index ba89415..03eb085 100644
    --- a/sound/pci/rme96.c
    +++ b/sound/pci/rme96.c
    @@ -704,10 +704,11 @@ snd_rme96_playback_setrate(struct rme96 *rme96,
    {
    /* change to/from double-speed: reset the DAC (if available) */
    snd_rme96_reset_dac(rme96);
    + return 1; /* need to restore volume */
    } else {
    writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
    + return 0;
    }
    - return 0;
    }

    static int
    @@ -945,6 +946,7 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
    struct rme96 *rme96 = snd_pcm_substream_chip(substream);
    struct snd_pcm_runtime *runtime = substream->runtime;
    int err, rate, dummy;
    + bool apply_dac_volume = false;

    runtime->dma_area = (void __force *)(rme96->iobase +
    RME96_IO_PLAY_BUFFER);
    @@ -958,24 +960,26 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
    {
    /* slave clock */
    if ((int)params_rate(params) != rate) {
    - spin_unlock_irq(&rme96->lock);
    - return -EIO;
    - }
    - } else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) {
    - spin_unlock_irq(&rme96->lock);
    - return err;
    - }
    - if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) {
    - spin_unlock_irq(&rme96->lock);
    - return err;
    + err = -EIO;
    + goto error;
    + }
    + } else {
    + err = snd_rme96_playback_setrate(rme96, params_rate(params));
    + if (err < 0)
    + goto error;
    + apply_dac_volume = err > 0; /* need to restore volume later? */
    }
    +
    + err = snd_rme96_playback_setformat(rme96, params_format(params));
    + if (err < 0)
    + goto error;
    snd_rme96_setframelog(rme96, params_channels(params), 1);
    if (rme96->capture_periodsize != 0) {
    if (params_period_size(params) << rme96->playback_frlog !=
    rme96->capture_periodsize)
    {
    - spin_unlock_irq(&rme96->lock);
    - return -EBUSY;
    + err = -EBUSY;
    + goto error;
    }
    }
    rme96->playback_periodsize =
    @@ -986,9 +990,16 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
    rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
    writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);
    }
    +
    + err = 0;
    + error:
    spin_unlock_irq(&rme96->lock);
    -
    - return 0;
    + if (apply_dac_volume) {
    + usleep_range(3000, 10000);
    + snd_rme96_apply_dac_volume(rme96);
    + }
    +
    + return err;
    }

    static int
    --
    1.9.1
    \
     
     \ /
      Last update: 2016-10-12 14:43    [W:4.079 / U:0.216 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site