root/sound/pci/cs5535audio/cs5535audio_pm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_cs5535audio_stop_hardware
  2. snd_cs5535audio_suspend
  3. snd_cs5535audio_resume

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Power management for audio on multifunction CS5535 companion device
   4  * Copyright (C) Jaya Kumar
   5  */
   6 
   7 #include <linux/init.h>
   8 #include <linux/pci.h>
   9 #include <linux/delay.h>
  10 #include <sound/core.h>
  11 #include <sound/control.h>
  12 #include <sound/initval.h>
  13 #include <sound/asoundef.h>
  14 #include <sound/pcm.h>
  15 #include <sound/ac97_codec.h>
  16 #include "cs5535audio.h"
  17 
  18 static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
  19 {
  20         /* 
  21         we depend on snd_ac97_suspend to tell the
  22         AC97 codec to shutdown. the amd spec suggests
  23         that the LNK_SHUTDOWN be done at the same time
  24         that the codec power-down is issued. instead,
  25         we do it just after rather than at the same 
  26         time. excluding codec specific build_ops->suspend
  27         ac97 powerdown hits:
  28         0x8000 EAPD 
  29         0x4000 Headphone amplifier 
  30         0x0300 ADC & DAC 
  31         0x0400 Analog Mixer powerdown (Vref on) 
  32         I am not sure if this is the best that we can do.
  33         The remainder to be investigated are:
  34         - analog mixer (vref off) 0x0800
  35         - AC-link powerdown 0x1000
  36         - codec internal clock 0x2000
  37         */
  38 
  39         /* set LNK_SHUTDOWN to shutdown AC link */
  40         cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN);
  41 
  42 }
  43 
  44 static int __maybe_unused snd_cs5535audio_suspend(struct device *dev)
  45 {
  46         struct snd_card *card = dev_get_drvdata(dev);
  47         struct cs5535audio *cs5535au = card->private_data;
  48         int i;
  49 
  50         snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
  51         snd_ac97_suspend(cs5535au->ac97);
  52         for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
  53                 struct cs5535audio_dma *dma = &cs5535au->dmas[i];
  54                 if (dma && dma->substream)
  55                         dma->saved_prd = dma->ops->read_prd(cs5535au);
  56         }
  57         /* save important regs, then disable aclink in hw */
  58         snd_cs5535audio_stop_hardware(cs5535au);
  59         return 0;
  60 }
  61 
  62 static int __maybe_unused snd_cs5535audio_resume(struct device *dev)
  63 {
  64         struct snd_card *card = dev_get_drvdata(dev);
  65         struct cs5535audio *cs5535au = card->private_data;
  66         u32 tmp;
  67         int timeout;
  68         int i;
  69 
  70         /* set LNK_WRM_RST to reset AC link */
  71         cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST);
  72 
  73         timeout = 50;
  74         do {
  75                 tmp = cs_readl(cs5535au, ACC_CODEC_STATUS);
  76                 if (tmp & PRM_RDY_STS)
  77                         break;
  78                 udelay(1);
  79         } while (--timeout);
  80 
  81         if (!timeout)
  82                 dev_err(cs5535au->card->dev, "Failure getting AC Link ready\n");
  83 
  84         /* set up rate regs, dma. actual initiation is done in trig */
  85         for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
  86                 struct cs5535audio_dma *dma = &cs5535au->dmas[i];
  87                 if (dma && dma->substream) {
  88                         dma->substream->ops->prepare(dma->substream);
  89                         dma->ops->setup_prd(cs5535au, dma->saved_prd);
  90                 }
  91         }
  92 
  93         /* we depend on ac97 to perform the codec power up */
  94         snd_ac97_resume(cs5535au->ac97);
  95         snd_power_change_state(card, SNDRV_CTL_POWER_D0);
  96 
  97         return 0;
  98 }
  99 
 100 SIMPLE_DEV_PM_OPS(snd_cs5535audio_pm, snd_cs5535audio_suspend, snd_cs5535audio_resume);

/* [<][>][^][v][top][bottom][index][help] */