diff options
Diffstat (limited to 'sound/pci/als4000.c')
-rw-r--r-- | sound/pci/als4000.c | 391 |
1 files changed, 293 insertions, 98 deletions
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 27ce6136ab00..ba570053d4d5 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. | 2 | * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. |
3 | * Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>, | 3 | * Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>, |
4 | * Jaroslav Kysela <perex@perex.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com> | 5 | * Copyright (C) 2002, 2008 by Andreas Mohr <hw7oshyuv3001@sneakemail.com> |
6 | * | 6 | * |
7 | * Framework borrowed from Massimo Piccioni's card-als100.c. | 7 | * Framework borrowed from Massimo Piccioni's card-als100.c. |
8 | * | 8 | * |
@@ -27,8 +27,10 @@ | |||
27 | * bought an ALS4000 based soundcard, I was forced to base this driver | 27 | * bought an ALS4000 based soundcard, I was forced to base this driver |
28 | * on reverse engineering. | 28 | * on reverse engineering. |
29 | * | 29 | * |
30 | * Note: this is no longer true. Pretty verbose chip docu (ALS4000a.PDF) | 30 | * Note: this is no longer true (thank you!): |
31 | * can be found on the ALSA web site. | 31 | * pretty verbose chip docu (ALS4000a.PDF) can be found on the ALSA web site. |
32 | * Page numbers stated anywhere below with the "SPECS_PAGE:" tag | ||
33 | * refer to: ALS4000a.PDF specs Ver 1.0, May 28th, 1998. | ||
32 | * | 34 | * |
33 | * The ALS4000 seems to be the PCI-cousin of the ALS100. It contains an | 35 | * The ALS4000 seems to be the PCI-cousin of the ALS100. It contains an |
34 | * ALS100-like SB DSP/mixer, an OPL3 synth, a MPU401 and a gameport | 36 | * ALS100-like SB DSP/mixer, an OPL3 synth, a MPU401 and a gameport |
@@ -59,7 +61,7 @@ | |||
59 | * - value -> some port 0x0c0d | 61 | * - value -> some port 0x0c0d |
60 | * | 62 | * |
61 | * ToDo: | 63 | * ToDo: |
62 | * - Proper shared IRQ handling? | 64 | * - by default, don't enable legacy game and use PCI game I/O |
63 | * - power management? (card can do voice wakeup according to datasheet!!) | 65 | * - power management? (card can do voice wakeup according to datasheet!!) |
64 | */ | 66 | */ |
65 | 67 | ||
@@ -78,7 +80,7 @@ | |||
78 | #include <sound/sb.h> | 80 | #include <sound/sb.h> |
79 | #include <sound/initval.h> | 81 | #include <sound/initval.h> |
80 | 82 | ||
81 | MODULE_AUTHOR("Bart Hartgers <bart@etpmod.phys.tue.nl>"); | 83 | MODULE_AUTHOR("Bart Hartgers <bart@etpmod.phys.tue.nl>, Andreas Mohr"); |
82 | MODULE_DESCRIPTION("Avance Logic ALS4000"); | 84 | MODULE_DESCRIPTION("Avance Logic ALS4000"); |
83 | MODULE_LICENSE("GPL"); | 85 | MODULE_LICENSE("GPL"); |
84 | MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}"); | 86 | MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}"); |
@@ -107,7 +109,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address for ALS4000 soundcard. (0 | |||
107 | 109 | ||
108 | struct snd_card_als4000 { | 110 | struct snd_card_als4000 { |
109 | /* most frequent access first */ | 111 | /* most frequent access first */ |
110 | unsigned long gcr; | 112 | unsigned long iobase; |
111 | struct pci_dev *pci; | 113 | struct pci_dev *pci; |
112 | struct snd_sb *chip; | 114 | struct snd_sb *chip; |
113 | #ifdef SUPPORT_JOYSTICK | 115 | #ifdef SUPPORT_JOYSTICK |
@@ -122,28 +124,168 @@ static struct pci_device_id snd_als4000_ids[] = { | |||
122 | 124 | ||
123 | MODULE_DEVICE_TABLE(pci, snd_als4000_ids); | 125 | MODULE_DEVICE_TABLE(pci, snd_als4000_ids); |
124 | 126 | ||
125 | static inline void snd_als4000_gcr_write_addr(unsigned long port, u32 reg, u32 val) | 127 | enum als4k_iobase_t { |
128 | /* IOx: B == Byte, W = Word, D = DWord; SPECS_PAGE: 37 */ | ||
129 | ALS4K_IOD_00_AC97_ACCESS = 0x00, | ||
130 | ALS4K_IOW_04_AC97_READ = 0x04, | ||
131 | ALS4K_IOB_06_AC97_STATUS = 0x06, | ||
132 | ALS4K_IOB_07_IRQSTATUS = 0x07, | ||
133 | ALS4K_IOD_08_GCR_DATA = 0x08, | ||
134 | ALS4K_IOB_0C_GCR_INDEX = 0x0c, | ||
135 | ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU = 0x0e, | ||
136 | ALS4K_IOB_10_ADLIB_ADDR0 = 0x10, | ||
137 | ALS4K_IOB_11_ADLIB_ADDR1 = 0x11, | ||
138 | ALS4K_IOB_12_ADLIB_ADDR2 = 0x12, | ||
139 | ALS4K_IOB_13_ADLIB_ADDR3 = 0x13, | ||
140 | ALS4K_IOB_14_MIXER_INDEX = 0x14, | ||
141 | ALS4K_IOB_15_MIXER_DATA = 0x15, | ||
142 | ALS4K_IOB_16_ESP_RESET = 0x16, | ||
143 | ALS4K_IOB_16_ACK_FOR_CR1E = 0x16, /* 2nd function */ | ||
144 | ALS4K_IOB_18_OPL_ADDR0 = 0x18, | ||
145 | ALS4K_IOB_19_OPL_ADDR1 = 0x19, | ||
146 | ALS4K_IOB_1A_ESP_RD_DATA = 0x1a, | ||
147 | ALS4K_IOB_1C_ESP_CMD_DATA = 0x1c, | ||
148 | ALS4K_IOB_1C_ESP_WR_STATUS = 0x1c, /* 2nd function */ | ||
149 | ALS4K_IOB_1E_ESP_RD_STATUS8 = 0x1e, | ||
150 | ALS4K_IOB_1F_ESP_RD_STATUS16 = 0x1f, | ||
151 | ALS4K_IOB_20_ESP_GAMEPORT_200 = 0x20, | ||
152 | ALS4K_IOB_21_ESP_GAMEPORT_201 = 0x21, | ||
153 | ALS4K_IOB_30_MIDI_DATA = 0x30, | ||
154 | ALS4K_IOB_31_MIDI_STATUS = 0x31, | ||
155 | ALS4K_IOB_31_MIDI_COMMAND = 0x31, /* 2nd function */ | ||
156 | }; | ||
157 | |||
158 | enum als4k_iobase_0e_t { | ||
159 | ALS4K_IOB_0E_MPU_IRQ = 0x10, | ||
160 | ALS4K_IOB_0E_CR1E_IRQ = 0x40, | ||
161 | ALS4K_IOB_0E_SB_DMA_IRQ = 0x80, | ||
162 | }; | ||
163 | |||
164 | enum als4k_gcr_t { /* all registers 32bit wide; SPECS_PAGE: 38 to 42 */ | ||
165 | ALS4K_GCR8C_MISC_CTRL = 0x8c, | ||
166 | ALS4K_GCR90_TEST_MODE_REG = 0x90, | ||
167 | ALS4K_GCR91_DMA0_ADDR = 0x91, | ||
168 | ALS4K_GCR92_DMA0_MODE_COUNT = 0x92, | ||
169 | ALS4K_GCR93_DMA1_ADDR = 0x93, | ||
170 | ALS4K_GCR94_DMA1_MODE_COUNT = 0x94, | ||
171 | ALS4K_GCR95_DMA3_ADDR = 0x95, | ||
172 | ALS4K_GCR96_DMA3_MODE_COUNT = 0x96, | ||
173 | ALS4K_GCR99_DMA_EMULATION_CTRL = 0x99, | ||
174 | ALS4K_GCRA0_FIFO1_CURRENT_ADDR = 0xa0, | ||
175 | ALS4K_GCRA1_FIFO1_STATUS_BYTECOUNT = 0xa1, | ||
176 | ALS4K_GCRA2_FIFO2_PCIADDR = 0xa2, | ||
177 | ALS4K_GCRA3_FIFO2_COUNT = 0xa3, | ||
178 | ALS4K_GCRA4_FIFO2_CURRENT_ADDR = 0xa4, | ||
179 | ALS4K_GCRA5_FIFO1_STATUS_BYTECOUNT = 0xa5, | ||
180 | ALS4K_GCRA6_PM_CTRL = 0xa6, | ||
181 | ALS4K_GCRA7_PCI_ACCESS_STORAGE = 0xa7, | ||
182 | ALS4K_GCRA8_LEGACY_CFG1 = 0xa8, | ||
183 | ALS4K_GCRA9_LEGACY_CFG2 = 0xa9, | ||
184 | ALS4K_GCRFF_DUMMY_SCRATCH = 0xff, | ||
185 | }; | ||
186 | |||
187 | enum als4k_gcr8c_t { | ||
188 | ALS4K_GCR8C_IRQ_MASK_CTRL_ENABLE = 0x8000, | ||
189 | ALS4K_GCR8C_CHIP_REV_MASK = 0xf0000 | ||
190 | }; | ||
191 | |||
192 | static inline void snd_als4k_iobase_writeb(unsigned long iobase, | ||
193 | enum als4k_iobase_t reg, | ||
194 | u8 val) | ||
195 | { | ||
196 | outb(val, iobase + reg); | ||
197 | } | ||
198 | |||
199 | static inline void snd_als4k_iobase_writel(unsigned long iobase, | ||
200 | enum als4k_iobase_t reg, | ||
201 | u32 val) | ||
202 | { | ||
203 | outl(val, iobase + reg); | ||
204 | } | ||
205 | |||
206 | static inline u8 snd_als4k_iobase_readb(unsigned long iobase, | ||
207 | enum als4k_iobase_t reg) | ||
208 | { | ||
209 | return inb(iobase + reg); | ||
210 | } | ||
211 | |||
212 | static inline u32 snd_als4k_iobase_readl(unsigned long iobase, | ||
213 | enum als4k_iobase_t reg) | ||
214 | { | ||
215 | return inl(iobase + reg); | ||
216 | } | ||
217 | |||
218 | static inline void snd_als4k_gcr_write_addr(unsigned long iobase, | ||
219 | enum als4k_gcr_t reg, | ||
220 | u32 val) | ||
126 | { | 221 | { |
127 | outb(reg, port+0x0c); | 222 | snd_als4k_iobase_writeb(iobase, ALS4K_IOB_0C_GCR_INDEX, reg); |
128 | outl(val, port+0x08); | 223 | snd_als4k_iobase_writel(iobase, ALS4K_IOD_08_GCR_DATA, val); |
129 | } | 224 | } |
130 | 225 | ||
131 | static inline void snd_als4000_gcr_write(struct snd_sb *sb, u32 reg, u32 val) | 226 | static inline void snd_als4k_gcr_write(struct snd_sb *sb, |
227 | enum als4k_gcr_t reg, | ||
228 | u32 val) | ||
132 | { | 229 | { |
133 | snd_als4000_gcr_write_addr(sb->alt_port, reg, val); | 230 | snd_als4k_gcr_write_addr(sb->alt_port, reg, val); |
134 | } | 231 | } |
135 | 232 | ||
136 | static inline u32 snd_als4000_gcr_read_addr(unsigned long port, u32 reg) | 233 | static inline u32 snd_als4k_gcr_read_addr(unsigned long iobase, |
234 | enum als4k_gcr_t reg) | ||
137 | { | 235 | { |
138 | outb(reg, port+0x0c); | 236 | /* SPECS_PAGE: 37/38 */ |
139 | return inl(port+0x08); | 237 | snd_als4k_iobase_writeb(iobase, ALS4K_IOB_0C_GCR_INDEX, reg); |
238 | return snd_als4k_iobase_readl(iobase, ALS4K_IOD_08_GCR_DATA); | ||
140 | } | 239 | } |
141 | 240 | ||
142 | static inline u32 snd_als4000_gcr_read(struct snd_sb *sb, u32 reg) | 241 | static inline u32 snd_als4k_gcr_read(struct snd_sb *sb, enum als4k_gcr_t reg) |
143 | { | 242 | { |
144 | return snd_als4000_gcr_read_addr(sb->alt_port, reg); | 243 | return snd_als4k_gcr_read_addr(sb->alt_port, reg); |
145 | } | 244 | } |
146 | 245 | ||
246 | enum als4k_cr_t { /* all registers 8bit wide; SPECS_PAGE: 20 to 23 */ | ||
247 | ALS4K_CR0_SB_CONFIG = 0x00, | ||
248 | ALS4K_CR2_MISC_CONTROL = 0x02, | ||
249 | ALS4K_CR3_CONFIGURATION = 0x03, | ||
250 | ALS4K_CR17_FIFO_STATUS = 0x17, | ||
251 | ALS4K_CR18_ESP_MAJOR_VERSION = 0x18, | ||
252 | ALS4K_CR19_ESP_MINOR_VERSION = 0x19, | ||
253 | ALS4K_CR1A_MPU401_UART_MODE_CONTROL = 0x1a, | ||
254 | ALS4K_CR1C_FIFO2_BLOCK_LENGTH_LO = 0x1c, | ||
255 | ALS4K_CR1D_FIFO2_BLOCK_LENGTH_HI = 0x1d, | ||
256 | ALS4K_CR1E_FIFO2_CONTROL = 0x1e, /* secondary PCM FIFO (recording) */ | ||
257 | ALS4K_CR3A_MISC_CONTROL = 0x3a, | ||
258 | ALS4K_CR3B_CRC32_BYTE0 = 0x3b, /* for testing, activate via CR3A */ | ||
259 | ALS4K_CR3C_CRC32_BYTE1 = 0x3c, | ||
260 | ALS4K_CR3D_CRC32_BYTE2 = 0x3d, | ||
261 | ALS4K_CR3E_CRC32_BYTE3 = 0x3e, | ||
262 | }; | ||
263 | |||
264 | enum als4k_cr0_t { | ||
265 | ALS4K_CR0_DMA_CONTIN_MODE_CTRL = 0x02, /* IRQ/FIFO controlled for 0/1 */ | ||
266 | ALS4K_CR0_DMA_90H_MODE_CTRL = 0x04, /* IRQ/FIFO controlled for 0/1 */ | ||
267 | ALS4K_CR0_MX80_81_REG_WRITE_ENABLE = 0x80, | ||
268 | }; | ||
269 | |||
270 | static inline void snd_als4_cr_write(struct snd_sb *chip, | ||
271 | enum als4k_cr_t reg, | ||
272 | u8 data) | ||
273 | { | ||
274 | /* Control Register is reg | 0xc0 (bit 7, 6 set) on sbmixer_index | ||
275 | * NOTE: assumes chip->mixer_lock to be locked externally already! | ||
276 | * SPECS_PAGE: 6 */ | ||
277 | snd_sbmixer_write(chip, reg | 0xc0, data); | ||
278 | } | ||
279 | |||
280 | static inline u8 snd_als4_cr_read(struct snd_sb *chip, | ||
281 | enum als4k_cr_t reg) | ||
282 | { | ||
283 | /* NOTE: assumes chip->mixer_lock to be locked externally already! */ | ||
284 | return snd_sbmixer_read(chip, reg | 0xc0); | ||
285 | } | ||
286 | |||
287 | |||
288 | |||
147 | static void snd_als4000_set_rate(struct snd_sb *chip, unsigned int rate) | 289 | static void snd_als4000_set_rate(struct snd_sb *chip, unsigned int rate) |
148 | { | 290 | { |
149 | if (!(chip->mode & SB_RATE_LOCK)) { | 291 | if (!(chip->mode & SB_RATE_LOCK)) { |
@@ -156,15 +298,19 @@ static void snd_als4000_set_rate(struct snd_sb *chip, unsigned int rate) | |||
156 | static inline void snd_als4000_set_capture_dma(struct snd_sb *chip, | 298 | static inline void snd_als4000_set_capture_dma(struct snd_sb *chip, |
157 | dma_addr_t addr, unsigned size) | 299 | dma_addr_t addr, unsigned size) |
158 | { | 300 | { |
159 | snd_als4000_gcr_write(chip, 0xa2, addr); | 301 | /* SPECS_PAGE: 40 */ |
160 | snd_als4000_gcr_write(chip, 0xa3, (size-1)); | 302 | snd_als4k_gcr_write(chip, ALS4K_GCRA2_FIFO2_PCIADDR, addr); |
303 | snd_als4k_gcr_write(chip, ALS4K_GCRA3_FIFO2_COUNT, (size-1)); | ||
161 | } | 304 | } |
162 | 305 | ||
163 | static inline void snd_als4000_set_playback_dma(struct snd_sb *chip, | 306 | static inline void snd_als4000_set_playback_dma(struct snd_sb *chip, |
164 | dma_addr_t addr, unsigned size) | 307 | dma_addr_t addr, |
308 | unsigned size) | ||
165 | { | 309 | { |
166 | snd_als4000_gcr_write(chip, 0x91, addr); | 310 | /* SPECS_PAGE: 38 */ |
167 | snd_als4000_gcr_write(chip, 0x92, (size-1)|0x180000); | 311 | snd_als4k_gcr_write(chip, ALS4K_GCR91_DMA0_ADDR, addr); |
312 | snd_als4k_gcr_write(chip, ALS4K_GCR92_DMA0_MODE_COUNT, | ||
313 | (size-1)|0x180000); | ||
168 | } | 314 | } |
169 | 315 | ||
170 | #define ALS4000_FORMAT_SIGNED (1<<0) | 316 | #define ALS4000_FORMAT_SIGNED (1<<0) |
@@ -248,7 +394,7 @@ static int snd_als4000_capture_prepare(struct snd_pcm_substream *substream) | |||
248 | count = snd_pcm_lib_period_bytes(substream); | 394 | count = snd_pcm_lib_period_bytes(substream); |
249 | 395 | ||
250 | if (chip->capture_format & ALS4000_FORMAT_16BIT) | 396 | if (chip->capture_format & ALS4000_FORMAT_16BIT) |
251 | count >>=1; | 397 | count >>= 1; |
252 | count--; | 398 | count--; |
253 | 399 | ||
254 | spin_lock_irq(&chip->reg_lock); | 400 | spin_lock_irq(&chip->reg_lock); |
@@ -256,8 +402,8 @@ static int snd_als4000_capture_prepare(struct snd_pcm_substream *substream) | |||
256 | snd_als4000_set_capture_dma(chip, runtime->dma_addr, size); | 402 | snd_als4000_set_capture_dma(chip, runtime->dma_addr, size); |
257 | spin_unlock_irq(&chip->reg_lock); | 403 | spin_unlock_irq(&chip->reg_lock); |
258 | spin_lock_irq(&chip->mixer_lock); | 404 | spin_lock_irq(&chip->mixer_lock); |
259 | snd_sbmixer_write(chip, 0xdc, count); | 405 | snd_als4_cr_write(chip, ALS4K_CR1C_FIFO2_BLOCK_LENGTH_LO, count & 0xff); |
260 | snd_sbmixer_write(chip, 0xdd, count>>8); | 406 | snd_als4_cr_write(chip, ALS4K_CR1D_FIFO2_BLOCK_LENGTH_HI, count >> 8); |
261 | spin_unlock_irq(&chip->mixer_lock); | 407 | spin_unlock_irq(&chip->mixer_lock); |
262 | return 0; | 408 | return 0; |
263 | } | 409 | } |
@@ -275,7 +421,7 @@ static int snd_als4000_playback_prepare(struct snd_pcm_substream *substream) | |||
275 | count = snd_pcm_lib_period_bytes(substream); | 421 | count = snd_pcm_lib_period_bytes(substream); |
276 | 422 | ||
277 | if (chip->playback_format & ALS4000_FORMAT_16BIT) | 423 | if (chip->playback_format & ALS4000_FORMAT_16BIT) |
278 | count >>=1; | 424 | count >>= 1; |
279 | count--; | 425 | count--; |
280 | 426 | ||
281 | /* FIXME: from second playback on, there's a lot more clicks and pops | 427 | /* FIXME: from second playback on, there's a lot more clicks and pops |
@@ -292,8 +438,8 @@ static int snd_als4000_playback_prepare(struct snd_pcm_substream *substream) | |||
292 | /* snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); */ | 438 | /* snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); */ |
293 | snd_sbdsp_command(chip, playback_cmd(chip).dsp_cmd); | 439 | snd_sbdsp_command(chip, playback_cmd(chip).dsp_cmd); |
294 | snd_sbdsp_command(chip, playback_cmd(chip).format); | 440 | snd_sbdsp_command(chip, playback_cmd(chip).format); |
295 | snd_sbdsp_command(chip, count); | 441 | snd_sbdsp_command(chip, count & 0xff); |
296 | snd_sbdsp_command(chip, count>>8); | 442 | snd_sbdsp_command(chip, count >> 8); |
297 | snd_sbdsp_command(chip, playback_cmd(chip).dma_off); | 443 | snd_sbdsp_command(chip, playback_cmd(chip).dma_off); |
298 | spin_unlock_irq(&chip->reg_lock); | 444 | spin_unlock_irq(&chip->reg_lock); |
299 | 445 | ||
@@ -305,17 +451,25 @@ static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int | |||
305 | struct snd_sb *chip = snd_pcm_substream_chip(substream); | 451 | struct snd_sb *chip = snd_pcm_substream_chip(substream); |
306 | int result = 0; | 452 | int result = 0; |
307 | 453 | ||
454 | /* FIXME race condition in here!!! | ||
455 | chip->mode non-atomic update gets consistently protected | ||
456 | by reg_lock always, _except_ for this place!! | ||
457 | Probably need to take reg_lock as outer (or inner??) lock, too. | ||
458 | (or serialize both lock operations? probably not, though... - racy?) | ||
459 | */ | ||
308 | spin_lock(&chip->mixer_lock); | 460 | spin_lock(&chip->mixer_lock); |
309 | switch (cmd) { | 461 | switch (cmd) { |
310 | case SNDRV_PCM_TRIGGER_START: | 462 | case SNDRV_PCM_TRIGGER_START: |
311 | case SNDRV_PCM_TRIGGER_RESUME: | 463 | case SNDRV_PCM_TRIGGER_RESUME: |
312 | chip->mode |= SB_RATE_LOCK_CAPTURE; | 464 | chip->mode |= SB_RATE_LOCK_CAPTURE; |
313 | snd_sbmixer_write(chip, 0xde, capture_cmd(chip)); | 465 | snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, |
466 | capture_cmd(chip)); | ||
314 | break; | 467 | break; |
315 | case SNDRV_PCM_TRIGGER_STOP: | 468 | case SNDRV_PCM_TRIGGER_STOP: |
316 | case SNDRV_PCM_TRIGGER_SUSPEND: | 469 | case SNDRV_PCM_TRIGGER_SUSPEND: |
317 | chip->mode &= ~SB_RATE_LOCK_CAPTURE; | 470 | chip->mode &= ~SB_RATE_LOCK_CAPTURE; |
318 | snd_sbmixer_write(chip, 0xde, 0); | 471 | snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, |
472 | capture_cmd(chip)); | ||
319 | break; | 473 | break; |
320 | default: | 474 | default: |
321 | result = -EINVAL; | 475 | result = -EINVAL; |
@@ -356,8 +510,9 @@ static snd_pcm_uframes_t snd_als4000_capture_pointer(struct snd_pcm_substream *s | |||
356 | unsigned int result; | 510 | unsigned int result; |
357 | 511 | ||
358 | spin_lock(&chip->reg_lock); | 512 | spin_lock(&chip->reg_lock); |
359 | result = snd_als4000_gcr_read(chip, 0xa4) & 0xffff; | 513 | result = snd_als4k_gcr_read(chip, ALS4K_GCRA4_FIFO2_CURRENT_ADDR); |
360 | spin_unlock(&chip->reg_lock); | 514 | spin_unlock(&chip->reg_lock); |
515 | result &= 0xffff; | ||
361 | return bytes_to_frames( substream->runtime, result ); | 516 | return bytes_to_frames( substream->runtime, result ); |
362 | } | 517 | } |
363 | 518 | ||
@@ -367,8 +522,9 @@ static snd_pcm_uframes_t snd_als4000_playback_pointer(struct snd_pcm_substream * | |||
367 | unsigned result; | 522 | unsigned result; |
368 | 523 | ||
369 | spin_lock(&chip->reg_lock); | 524 | spin_lock(&chip->reg_lock); |
370 | result = snd_als4000_gcr_read(chip, 0xa0) & 0xffff; | 525 | result = snd_als4k_gcr_read(chip, ALS4K_GCRA0_FIFO1_CURRENT_ADDR); |
371 | spin_unlock(&chip->reg_lock); | 526 | spin_unlock(&chip->reg_lock); |
527 | result &= 0xffff; | ||
372 | return bytes_to_frames( substream->runtime, result ); | 528 | return bytes_to_frames( substream->runtime, result ); |
373 | } | 529 | } |
374 | 530 | ||
@@ -376,45 +532,63 @@ static snd_pcm_uframes_t snd_als4000_playback_pointer(struct snd_pcm_substream * | |||
376 | * return IRQ_HANDLED no matter whether we actually had an IRQ flag or not). | 532 | * return IRQ_HANDLED no matter whether we actually had an IRQ flag or not). |
377 | * ALS4000a.PDF writes that while ACKing IRQ in PCI block will *not* ACK | 533 | * ALS4000a.PDF writes that while ACKing IRQ in PCI block will *not* ACK |
378 | * the IRQ in the SB core, ACKing IRQ in SB block *will* ACK the PCI IRQ | 534 | * the IRQ in the SB core, ACKing IRQ in SB block *will* ACK the PCI IRQ |
379 | * register (alt_port + 0x0e). Probably something could be optimized here to | 535 | * register (alt_port + ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU). Probably something |
380 | * query/write one register only... | 536 | * could be optimized here to query/write one register only... |
381 | * And even if both registers need to be queried, then there's still the | 537 | * And even if both registers need to be queried, then there's still the |
382 | * question of whether it's actually correct to ACK PCI IRQ before reading | 538 | * question of whether it's actually correct to ACK PCI IRQ before reading |
383 | * SB IRQ like we do now, since ALS4000a.PDF mentions that PCI IRQ will *clear* | 539 | * SB IRQ like we do now, since ALS4000a.PDF mentions that PCI IRQ will *clear* |
384 | * SB IRQ status. | 540 | * SB IRQ status. |
541 | * (hmm, SPECS_PAGE: 38 mentions it the other way around!) | ||
385 | * And do we *really* need the lock here for *reading* SB_DSP4_IRQSTATUS?? | 542 | * And do we *really* need the lock here for *reading* SB_DSP4_IRQSTATUS?? |
386 | * */ | 543 | * */ |
387 | static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id) | 544 | static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id) |
388 | { | 545 | { |
389 | struct snd_sb *chip = dev_id; | 546 | struct snd_sb *chip = dev_id; |
390 | unsigned gcr_status; | 547 | unsigned pci_irqstatus; |
391 | unsigned sb_status; | 548 | unsigned sb_irqstatus; |
392 | 549 | ||
393 | /* find out which bit of the ALS4000 produced the interrupt */ | 550 | /* find out which bit of the ALS4000 PCI block produced the interrupt, |
394 | gcr_status = inb(chip->alt_port + 0xe); | 551 | SPECS_PAGE: 38, 5 */ |
395 | 552 | pci_irqstatus = snd_als4k_iobase_readb(chip->alt_port, | |
396 | if ((gcr_status & 0x80) && (chip->playback_substream)) /* playback */ | 553 | ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU); |
554 | if ((pci_irqstatus & ALS4K_IOB_0E_SB_DMA_IRQ) | ||
555 | && (chip->playback_substream)) /* playback */ | ||
397 | snd_pcm_period_elapsed(chip->playback_substream); | 556 | snd_pcm_period_elapsed(chip->playback_substream); |
398 | if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */ | 557 | if ((pci_irqstatus & ALS4K_IOB_0E_CR1E_IRQ) |
558 | && (chip->capture_substream)) /* capturing */ | ||
399 | snd_pcm_period_elapsed(chip->capture_substream); | 559 | snd_pcm_period_elapsed(chip->capture_substream); |
400 | if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */ | 560 | if ((pci_irqstatus & ALS4K_IOB_0E_MPU_IRQ) |
561 | && (chip->rmidi)) /* MPU401 interrupt */ | ||
401 | snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); | 562 | snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); |
402 | /* release the gcr */ | 563 | /* ACK the PCI block IRQ */ |
403 | outb(gcr_status, chip->alt_port + 0xe); | 564 | snd_als4k_iobase_writeb(chip->alt_port, |
565 | ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU, pci_irqstatus); | ||
404 | 566 | ||
405 | spin_lock(&chip->mixer_lock); | 567 | spin_lock(&chip->mixer_lock); |
406 | sb_status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); | 568 | /* SPECS_PAGE: 20 */ |
569 | sb_irqstatus = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); | ||
407 | spin_unlock(&chip->mixer_lock); | 570 | spin_unlock(&chip->mixer_lock); |
408 | 571 | ||
409 | if (sb_status & SB_IRQTYPE_8BIT) | 572 | if (sb_irqstatus & SB_IRQTYPE_8BIT) |
410 | snd_sb_ack_8bit(chip); | 573 | snd_sb_ack_8bit(chip); |
411 | if (sb_status & SB_IRQTYPE_16BIT) | 574 | if (sb_irqstatus & SB_IRQTYPE_16BIT) |
412 | snd_sb_ack_16bit(chip); | 575 | snd_sb_ack_16bit(chip); |
413 | if (sb_status & SB_IRQTYPE_MPUIN) | 576 | if (sb_irqstatus & SB_IRQTYPE_MPUIN) |
414 | inb(chip->mpu_port); | 577 | inb(chip->mpu_port); |
415 | if (sb_status & 0x20) | 578 | if (sb_irqstatus & ALS4K_IRQTYPE_CR1E_DMA) |
416 | inb(SBP(chip, RESET)); | 579 | snd_als4k_iobase_readb(chip->alt_port, |
417 | return IRQ_HANDLED; | 580 | ALS4K_IOB_16_ACK_FOR_CR1E); |
581 | |||
582 | /* printk(KERN_INFO "als4000: irq 0x%04x 0x%04x\n", | ||
583 | pci_irqstatus, sb_irqstatus); */ | ||
584 | |||
585 | /* only ack the things we actually handled above */ | ||
586 | return IRQ_RETVAL( | ||
587 | (pci_irqstatus & (ALS4K_IOB_0E_SB_DMA_IRQ|ALS4K_IOB_0E_CR1E_IRQ| | ||
588 | ALS4K_IOB_0E_MPU_IRQ)) | ||
589 | || (sb_irqstatus & (SB_IRQTYPE_8BIT|SB_IRQTYPE_16BIT| | ||
590 | SB_IRQTYPE_MPUIN|ALS4K_IRQTYPE_CR1E_DMA)) | ||
591 | ); | ||
418 | } | 592 | } |
419 | 593 | ||
420 | /*****************************************************************/ | 594 | /*****************************************************************/ |
@@ -526,7 +700,8 @@ static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device) | |||
526 | struct snd_pcm *pcm; | 700 | struct snd_pcm *pcm; |
527 | int err; | 701 | int err; |
528 | 702 | ||
529 | if ((err = snd_pcm_new(chip->card, "ALS4000 DSP", device, 1, 1, &pcm)) < 0) | 703 | err = snd_pcm_new(chip->card, "ALS4000 DSP", device, 1, 1, &pcm); |
704 | if (err < 0) | ||
530 | return err; | 705 | return err; |
531 | pcm->private_data = chip; | 706 | pcm->private_data = chip; |
532 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | 707 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; |
@@ -543,48 +718,55 @@ static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device) | |||
543 | 718 | ||
544 | /******************************************************************/ | 719 | /******************************************************************/ |
545 | 720 | ||
546 | static void snd_als4000_set_addr(unsigned long gcr, | 721 | static void snd_als4000_set_addr(unsigned long iobase, |
547 | unsigned int sb, | 722 | unsigned int sb_io, |
548 | unsigned int mpu, | 723 | unsigned int mpu_io, |
549 | unsigned int opl, | 724 | unsigned int opl_io, |
550 | unsigned int game) | 725 | unsigned int game_io) |
551 | { | 726 | { |
552 | u32 confA = 0; | 727 | u32 cfg1 = 0; |
553 | u32 confB = 0; | 728 | u32 cfg2 = 0; |
554 | 729 | ||
555 | if (mpu > 0) | 730 | if (mpu_io > 0) |
556 | confB |= (mpu | 1) << 16; | 731 | cfg2 |= (mpu_io | 1) << 16; |
557 | if (sb > 0) | 732 | if (sb_io > 0) |
558 | confB |= (sb | 1); | 733 | cfg2 |= (sb_io | 1); |
559 | if (game > 0) | 734 | if (game_io > 0) |
560 | confA |= (game | 1) << 16; | 735 | cfg1 |= (game_io | 1) << 16; |
561 | if (opl > 0) | 736 | if (opl_io > 0) |
562 | confA |= (opl | 1); | 737 | cfg1 |= (opl_io | 1); |
563 | snd_als4000_gcr_write_addr(gcr, 0xa8, confA); | 738 | snd_als4k_gcr_write_addr(iobase, ALS4K_GCRA8_LEGACY_CFG1, cfg1); |
564 | snd_als4000_gcr_write_addr(gcr, 0xa9, confB); | 739 | snd_als4k_gcr_write_addr(iobase, ALS4K_GCRA9_LEGACY_CFG2, cfg2); |
565 | } | 740 | } |
566 | 741 | ||
567 | static void snd_als4000_configure(struct snd_sb *chip) | 742 | static void snd_als4000_configure(struct snd_sb *chip) |
568 | { | 743 | { |
569 | unsigned tmp; | 744 | u8 tmp; |
570 | int i; | 745 | int i; |
571 | 746 | ||
572 | /* do some more configuration */ | 747 | /* do some more configuration */ |
573 | spin_lock_irq(&chip->mixer_lock); | 748 | spin_lock_irq(&chip->mixer_lock); |
574 | tmp = snd_sbmixer_read(chip, 0xc0); | 749 | tmp = snd_als4_cr_read(chip, ALS4K_CR0_SB_CONFIG); |
575 | snd_sbmixer_write(chip, 0xc0, tmp|0x80); | 750 | snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, |
576 | /* always select DMA channel 0, since we do not actually use DMA */ | 751 | tmp|ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); |
752 | /* always select DMA channel 0, since we do not actually use DMA | ||
753 | * SPECS_PAGE: 19/20 */ | ||
577 | snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0); | 754 | snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0); |
578 | snd_sbmixer_write(chip, 0xc0, tmp&0x7f); | 755 | snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, |
756 | tmp & ~ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); | ||
579 | spin_unlock_irq(&chip->mixer_lock); | 757 | spin_unlock_irq(&chip->mixer_lock); |
580 | 758 | ||
581 | spin_lock_irq(&chip->reg_lock); | 759 | spin_lock_irq(&chip->reg_lock); |
582 | /* magic number. Enables interrupts(?) */ | 760 | /* enable interrupts */ |
583 | snd_als4000_gcr_write(chip, 0x8c, 0x28000); | 761 | snd_als4k_gcr_write(chip, ALS4K_GCR8C_MISC_CTRL, |
584 | for(i = 0x91; i <= 0x96; ++i) | 762 | ALS4K_GCR8C_IRQ_MASK_CTRL_ENABLE); |
585 | snd_als4000_gcr_write(chip, i, 0); | 763 | |
764 | /* SPECS_PAGE: 39 */ | ||
765 | for (i = ALS4K_GCR91_DMA0_ADDR; i <= ALS4K_GCR96_DMA3_MODE_COUNT; ++i) | ||
766 | snd_als4k_gcr_write(chip, i, 0); | ||
586 | 767 | ||
587 | snd_als4000_gcr_write(chip, 0x99, snd_als4000_gcr_read(chip, 0x99)); | 768 | snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL, |
769 | snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL)); | ||
588 | spin_unlock_irq(&chip->reg_lock); | 770 | spin_unlock_irq(&chip->reg_lock); |
589 | } | 771 | } |
590 | 772 | ||
@@ -628,7 +810,7 @@ static int __devinit snd_als4000_create_gameport(struct snd_card_als4000 *acard, | |||
628 | gameport_set_port_data(gp, r); | 810 | gameport_set_port_data(gp, r); |
629 | 811 | ||
630 | /* Enable legacy joystick port */ | 812 | /* Enable legacy joystick port */ |
631 | snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1); | 813 | snd_als4000_set_addr(acard->iobase, 0, 0, 0, 1); |
632 | 814 | ||
633 | gameport_register_port(acard->gameport); | 815 | gameport_register_port(acard->gameport); |
634 | 816 | ||
@@ -643,7 +825,9 @@ static void snd_als4000_free_gameport(struct snd_card_als4000 *acard) | |||
643 | gameport_unregister_port(acard->gameport); | 825 | gameport_unregister_port(acard->gameport); |
644 | acard->gameport = NULL; | 826 | acard->gameport = NULL; |
645 | 827 | ||
646 | snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */ | 828 | /* disable joystick */ |
829 | snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0); | ||
830 | |||
647 | release_and_free_resource(r); | 831 | release_and_free_resource(r); |
648 | } | 832 | } |
649 | } | 833 | } |
@@ -654,10 +838,10 @@ static inline void snd_als4000_free_gameport(struct snd_card_als4000 *acard) { } | |||
654 | 838 | ||
655 | static void snd_card_als4000_free( struct snd_card *card ) | 839 | static void snd_card_als4000_free( struct snd_card *card ) |
656 | { | 840 | { |
657 | struct snd_card_als4000 * acard = (struct snd_card_als4000 *)card->private_data; | 841 | struct snd_card_als4000 *acard = card->private_data; |
658 | 842 | ||
659 | /* make sure that interrupts are disabled */ | 843 | /* make sure that interrupts are disabled */ |
660 | snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0); | 844 | snd_als4k_gcr_write_addr(acard->iobase, ALS4K_GCR8C_MISC_CTRL, 0); |
661 | /* free resources */ | 845 | /* free resources */ |
662 | snd_als4000_free_gameport(acard); | 846 | snd_als4000_free_gameport(acard); |
663 | pci_release_regions(acard->pci); | 847 | pci_release_regions(acard->pci); |
@@ -670,7 +854,7 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
670 | static int dev; | 854 | static int dev; |
671 | struct snd_card *card; | 855 | struct snd_card *card; |
672 | struct snd_card_als4000 *acard; | 856 | struct snd_card_als4000 *acard; |
673 | unsigned long gcr; | 857 | unsigned long iobase; |
674 | struct snd_sb *chip; | 858 | struct snd_sb *chip; |
675 | struct snd_opl3 *opl3; | 859 | struct snd_opl3 *opl3; |
676 | unsigned short word; | 860 | unsigned short word; |
@@ -699,31 +883,32 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
699 | pci_disable_device(pci); | 883 | pci_disable_device(pci); |
700 | return err; | 884 | return err; |
701 | } | 885 | } |
702 | gcr = pci_resource_start(pci, 0); | 886 | iobase = pci_resource_start(pci, 0); |
703 | 887 | ||
704 | pci_read_config_word(pci, PCI_COMMAND, &word); | 888 | pci_read_config_word(pci, PCI_COMMAND, &word); |
705 | pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); | 889 | pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); |
706 | pci_set_master(pci); | 890 | pci_set_master(pci); |
707 | 891 | ||
708 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 892 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, |
709 | sizeof( struct snd_card_als4000 ) ); | 893 | sizeof(*acard) /* private_data: acard */); |
710 | if (card == NULL) { | 894 | if (card == NULL) { |
711 | pci_release_regions(pci); | 895 | pci_release_regions(pci); |
712 | pci_disable_device(pci); | 896 | pci_disable_device(pci); |
713 | return -ENOMEM; | 897 | return -ENOMEM; |
714 | } | 898 | } |
715 | 899 | ||
716 | acard = (struct snd_card_als4000 *)card->private_data; | 900 | acard = card->private_data; |
717 | acard->pci = pci; | 901 | acard->pci = pci; |
718 | acard->gcr = gcr; | 902 | acard->iobase = iobase; |
719 | card->private_free = snd_card_als4000_free; | 903 | card->private_free = snd_card_als4000_free; |
720 | 904 | ||
721 | /* disable all legacy ISA stuff */ | 905 | /* disable all legacy ISA stuff */ |
722 | snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); | 906 | snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0); |
723 | 907 | ||
724 | if ((err = snd_sbdsp_create(card, | 908 | if ((err = snd_sbdsp_create(card, |
725 | gcr + 0x10, | 909 | iobase + ALS4K_IOB_10_ADLIB_ADDR0, |
726 | pci->irq, | 910 | pci->irq, |
911 | /* internally registered as IRQF_SHARED in case of ALS4000 SB */ | ||
727 | snd_als4000_interrupt, | 912 | snd_als4000_interrupt, |
728 | -1, | 913 | -1, |
729 | -1, | 914 | -1, |
@@ -734,7 +919,7 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
734 | acard->chip = chip; | 919 | acard->chip = chip; |
735 | 920 | ||
736 | chip->pci = pci; | 921 | chip->pci = pci; |
737 | chip->alt_port = gcr; | 922 | chip->alt_port = iobase; |
738 | snd_card_set_dev(card, &pci->dev); | 923 | snd_card_set_dev(card, &pci->dev); |
739 | 924 | ||
740 | snd_als4000_configure(chip); | 925 | snd_als4000_configure(chip); |
@@ -745,11 +930,18 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
745 | card->shortname, chip->alt_port, chip->irq); | 930 | card->shortname, chip->alt_port, chip->irq); |
746 | 931 | ||
747 | if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, | 932 | if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, |
748 | gcr+0x30, MPU401_INFO_INTEGRATED, | 933 | iobase + ALS4K_IOB_30_MIDI_DATA, |
934 | MPU401_INFO_INTEGRATED, | ||
749 | pci->irq, 0, &chip->rmidi)) < 0) { | 935 | pci->irq, 0, &chip->rmidi)) < 0) { |
750 | printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30); | 936 | printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", |
937 | iobase + ALS4K_IOB_30_MIDI_DATA); | ||
751 | goto out_err; | 938 | goto out_err; |
752 | } | 939 | } |
940 | /* FIXME: ALS4000 has interesting MPU401 configuration features | ||
941 | * at ALS4K_CR1A_MPU401_UART_MODE_CONTROL | ||
942 | * (pass-thru / UART switching, fast MIDI clock, etc.), | ||
943 | * however there doesn't seem to be an ALSA API for this... | ||
944 | * SPECS_PAGE: 21 */ | ||
753 | 945 | ||
754 | if ((err = snd_als4000_pcm(chip, 0)) < 0) { | 946 | if ((err = snd_als4000_pcm(chip, 0)) < 0) { |
755 | goto out_err; | 947 | goto out_err; |
@@ -758,10 +950,13 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
758 | goto out_err; | 950 | goto out_err; |
759 | } | 951 | } |
760 | 952 | ||
761 | if (snd_opl3_create(card, gcr+0x10, gcr+0x12, | 953 | if (snd_opl3_create(card, |
954 | iobase + ALS4K_IOB_10_ADLIB_ADDR0, | ||
955 | iobase + ALS4K_IOB_12_ADLIB_ADDR2, | ||
762 | OPL3_HW_AUTO, 1, &opl3) < 0) { | 956 | OPL3_HW_AUTO, 1, &opl3) < 0) { |
763 | printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx?\n", | 957 | printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx?\n", |
764 | gcr+0x10, gcr+0x12 ); | 958 | iobase + ALS4K_IOB_10_ADLIB_ADDR0, |
959 | iobase + ALS4K_IOB_12_ADLIB_ADDR2); | ||
765 | } else { | 960 | } else { |
766 | if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { | 961 | if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { |
767 | goto out_err; | 962 | goto out_err; |
@@ -831,13 +1026,13 @@ static int snd_als4000_resume(struct pci_dev *pci) | |||
831 | 1026 | ||
832 | #ifdef SUPPORT_JOYSTICK | 1027 | #ifdef SUPPORT_JOYSTICK |
833 | if (acard->gameport) | 1028 | if (acard->gameport) |
834 | snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1); | 1029 | snd_als4000_set_addr(acard->iobase, 0, 0, 0, 1); |
835 | #endif | 1030 | #endif |
836 | 1031 | ||
837 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1032 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
838 | return 0; | 1033 | return 0; |
839 | } | 1034 | } |
840 | #endif | 1035 | #endif /* CONFIG_PM */ |
841 | 1036 | ||
842 | 1037 | ||
843 | static struct pci_driver driver = { | 1038 | static struct pci_driver driver = { |