1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/init.h>
22#include <linux/pci.h>
23#include <linux/delay.h>
24#include <sound/core.h>
25#include <sound/control.h>
26#include <sound/initval.h>
27#include <sound/asoundef.h>
28#include <sound/pcm.h>
29#include <sound/ac97_codec.h>
30#include "cs5535audio.h"
31
32static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
33{
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN);
55
56}
57
58static int __maybe_unused snd_cs5535audio_suspend(struct device *dev)
59{
60 struct snd_card *card = dev_get_drvdata(dev);
61 struct cs5535audio *cs5535au = card->private_data;
62 int i;
63
64 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
65 snd_pcm_suspend_all(cs5535au->pcm);
66 snd_ac97_suspend(cs5535au->ac97);
67 for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
68 struct cs5535audio_dma *dma = &cs5535au->dmas[i];
69 if (dma && dma->substream)
70 dma->saved_prd = dma->ops->read_prd(cs5535au);
71 }
72
73 snd_cs5535audio_stop_hardware(cs5535au);
74 return 0;
75}
76
77static int __maybe_unused snd_cs5535audio_resume(struct device *dev)
78{
79 struct snd_card *card = dev_get_drvdata(dev);
80 struct cs5535audio *cs5535au = card->private_data;
81 u32 tmp;
82 int timeout;
83 int i;
84
85
86 cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST);
87
88 timeout = 50;
89 do {
90 tmp = cs_readl(cs5535au, ACC_CODEC_STATUS);
91 if (tmp & PRM_RDY_STS)
92 break;
93 udelay(1);
94 } while (--timeout);
95
96 if (!timeout)
97 dev_err(cs5535au->card->dev, "Failure getting AC Link ready\n");
98
99
100 for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
101 struct cs5535audio_dma *dma = &cs5535au->dmas[i];
102 if (dma && dma->substream) {
103 dma->substream->ops->prepare(dma->substream);
104 dma->ops->setup_prd(cs5535au, dma->saved_prd);
105 }
106 }
107
108
109 snd_ac97_resume(cs5535au->ac97);
110 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
111
112 return 0;
113}
114
115SIMPLE_DEV_PM_OPS(snd_cs5535audio_pm, snd_cs5535audio_suspend, snd_cs5535audio_resume);
116