Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: azt3328: fix previous breakage, improve suspend, cleanups

- fix my previous codec activity breakage (_non-warned_ variable assignment
issue)
- convert suspend/resume to 32bit I/O access (I/O is painful; to improve
suspend/resume performance)
- change DEBUG_PLAY_REC to DEBUG_CODEC for consistency
- printk cleanup
- some logging improvements
- minor cleanup/improvements

The variable assignment issue above was a conditional assignment to the
call_function variable (this ended with the non-preinitialized variable
not getting assigned in some cases, thus a dangling stack value, yet gcc 4.3.3
unbelievably did _NOT_ warn about it in this case!!),
needed to change this into _always_ assigning the check result.
Practical result of this bug was that when shutting down
_either_ playback or capture, _both_ streams dropped dead :P

Tested, working (plus resume) and checkpatch.pl:ed on 2.6.30-rc5,
applies cleanly to 2.6.30 proper with my previous (committed)
patches applied.

Signed-off-by: Andreas Mohr <andi@lisas.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Andreas Mohr and committed by
Takashi Iwai
78df617a dfbf9511

+135 -81
+124 -76
sound/pci/azt3328.c
··· 15 15 * has very good support out of the box; 16 16 * just to make sure that the right people hit this and get to know that, 17 17 * despite the high level of Internet ignorance - as usual :-P - 18 - * about Linux support for this card) 18 + * about very good support for this card - on Linux!) 19 19 * 20 20 * GPL LICENSE 21 21 * This program is free software; you can redistribute it and/or modify ··· 222 222 #define DEBUG_MISC 0 223 223 #define DEBUG_CALLS 0 224 224 #define DEBUG_MIXER 0 225 - #define DEBUG_PLAY_REC 0 225 + #define DEBUG_CODEC 0 226 226 #define DEBUG_IO 0 227 227 #define DEBUG_TIMER 0 228 228 #define DEBUG_GAME 0 229 + #define DEBUG_PM 0 229 230 #define MIXER_TESTING 0 230 231 231 232 #if DEBUG_MISC 232 - #define snd_azf3328_dbgmisc(format, args...) printk(KERN_ERR format, ##args) 233 + #define snd_azf3328_dbgmisc(format, args...) printk(KERN_DEBUG format, ##args) 233 234 #else 234 235 #define snd_azf3328_dbgmisc(format, args...) 235 236 #endif 236 237 237 238 #if DEBUG_CALLS 238 239 #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args) 239 - #define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__) 240 - #define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__) 240 + #define snd_azf3328_dbgcallenter() printk(KERN_DEBUG "--> %s\n", __func__) 241 + #define snd_azf3328_dbgcallleave() printk(KERN_DEBUG "<-- %s\n", __func__) 241 242 #else 242 243 #define snd_azf3328_dbgcalls(format, args...) 243 244 #define snd_azf3328_dbgcallenter() ··· 251 250 #define snd_azf3328_dbgmixer(format, args...) 252 251 #endif 253 252 254 - #if DEBUG_PLAY_REC 255 - #define snd_azf3328_dbgplay(format, args...) printk(KERN_DEBUG format, ##args) 253 + #if DEBUG_CODEC 254 + #define snd_azf3328_dbgcodec(format, args...) printk(KERN_DEBUG format, ##args) 256 255 #else 257 - #define snd_azf3328_dbgplay(format, args...) 256 + #define snd_azf3328_dbgcodec(format, args...) 258 257 #endif 259 258 260 259 #if DEBUG_MISC ··· 267 266 #define snd_azf3328_dbggame(format, args...) printk(KERN_DEBUG format, ##args) 268 267 #else 269 268 #define snd_azf3328_dbggame(format, args...) 269 + #endif 270 + 271 + #if DEBUG_PM 272 + #define snd_azf3328_dbgpm(format, args...) printk(KERN_DEBUG format, ##args) 273 + #else 274 + #define snd_azf3328_dbgpm(format, args...) 270 275 #endif 271 276 272 277 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ ··· 341 334 342 335 #ifdef CONFIG_PM 343 336 /* register value containers for power management 344 - * Note: not always full I/O range preserved (just like Win driver!) */ 345 - u16 saved_regs_ctrl[AZF_IO_SIZE_CTRL_PM / 2]; 346 - u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2]; 347 - u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2]; 348 - u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2]; 349 - u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2]; 337 + * Note: not always full I/O range preserved (similar to Win driver!) */ 338 + u32 saved_regs_ctrl[AZF_ALIGN(AZF_IO_SIZE_CTRL_PM) / 4]; 339 + u32 saved_regs_game[AZF_ALIGN(AZF_IO_SIZE_GAME_PM) / 4]; 340 + u32 saved_regs_mpu[AZF_ALIGN(AZF_IO_SIZE_MPU_PM) / 4]; 341 + u32 saved_regs_opl3[AZF_ALIGN(AZF_IO_SIZE_OPL3_PM) / 4]; 342 + u32 saved_regs_mixer[AZF_ALIGN(AZF_IO_SIZE_MIXER_PM) / 4]; 350 343 #endif 351 344 }; 352 345 ··· 1036 1029 bool enable 1037 1030 ) 1038 1031 { 1039 - if (enable) 1040 - chip->shadow_reg_ctrl_6AH &= ~bitmask; 1041 - else 1032 + bool do_mask = !enable; 1033 + if (do_mask) 1042 1034 chip->shadow_reg_ctrl_6AH |= bitmask; 1043 - snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n", 1044 - bitmask, enable, chip->shadow_reg_ctrl_6AH); 1035 + else 1036 + chip->shadow_reg_ctrl_6AH &= ~bitmask; 1037 + snd_azf3328_dbgcodec("6AH_update mask 0x%04x do_mask %d: val 0x%04x\n", 1038 + bitmask, do_mask, chip->shadow_reg_ctrl_6AH); 1045 1039 snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH); 1046 1040 } 1047 1041 1048 1042 static inline void 1049 1043 snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable) 1050 1044 { 1051 - snd_azf3328_dbgplay("codec_enable %d\n", enable); 1045 + snd_azf3328_dbgcodec("codec_enable %d\n", enable); 1052 1046 /* no idea what exactly is being done here, but I strongly assume it's 1053 1047 * PM related */ 1054 1048 snd_azf3328_ctrl_reg_6AH_update( ··· 1066 1058 struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; 1067 1059 bool need_change = (codec->running != enable); 1068 1060 1069 - snd_azf3328_dbgplay( 1061 + snd_azf3328_dbgcodec( 1070 1062 "codec_activity: %s codec, enable %d, need_change %d\n", 1071 1063 codec->name, enable, need_change 1072 1064 ); ··· 1089 1081 (which globally shuts down operation of codecs) 1090 1082 only in case the other codecs are currently 1091 1083 not active either! */ 1092 - if ((!chip->codecs[peer_codecs[codec_type].other1] 1093 - .running) 1094 - && (!chip->codecs[peer_codecs[codec_type].other2] 1095 - .running)) 1096 - call_function = 1; 1084 + call_function = 1085 + ((!chip->codecs[peer_codecs[codec_type].other1] 1086 + .running) 1087 + && (!chip->codecs[peer_codecs[codec_type].other2] 1088 + .running)); 1097 1089 } 1098 1090 if (call_function) 1099 1091 snd_azf3328_ctrl_enable_codecs(chip, enable); ··· 1105 1097 chip, 1106 1098 codec_type 1107 1099 ); 1100 + codec->running = enable; 1108 1101 } 1109 - codec->running = enable; 1110 1102 } 1111 1103 1112 1104 static void ··· 1122 1114 if (!codec->running) { 1123 1115 /* AZF3328 uses a two buffer pointer DMA transfer approach */ 1124 1116 1125 - unsigned long flags; 1117 + unsigned long flags, addr_area2; 1126 1118 1127 1119 /* width 32bit (prevent overflow): */ 1128 - u32 addr_area2, count_areas, lengths; 1120 + u32 count_areas, lengths; 1129 1121 1130 1122 count_areas = size/2; 1131 1123 addr_area2 = addr+count_areas; 1132 1124 count_areas--; /* max. index */ 1133 - snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas); 1125 + snd_azf3328_dbgcodec("setdma: buffers %08lx[%u] / %08lx[%u]\n", 1126 + addr, count_areas, addr_area2, count_areas); 1134 1127 1135 1128 /* build combined I/O buffer length word */ 1136 1129 lengths = (count_areas << 16) | (count_areas); ··· 1185 1176 1186 1177 switch (cmd) { 1187 1178 case SNDRV_PCM_TRIGGER_START: 1188 - snd_azf3328_dbgplay("START %s\n", codec->name); 1179 + snd_azf3328_dbgcodec("START %s\n", codec->name); 1189 1180 1190 1181 if (is_playback_codec) { 1191 1182 /* mute WaveOut (avoid clicking during setup) */ ··· 1252 1243 ); 1253 1244 } 1254 1245 1255 - snd_azf3328_dbgplay("STARTED %s\n", codec->name); 1246 + snd_azf3328_dbgcodec("STARTED %s\n", codec->name); 1256 1247 break; 1257 1248 case SNDRV_PCM_TRIGGER_RESUME: 1258 - snd_azf3328_dbgplay("RESUME %s\n", codec->name); 1249 + snd_azf3328_dbgcodec("RESUME %s\n", codec->name); 1259 1250 /* resume codec if we were active */ 1260 1251 spin_lock(&chip->reg_lock); 1261 1252 if (codec->running) ··· 1267 1258 spin_unlock(&chip->reg_lock); 1268 1259 break; 1269 1260 case SNDRV_PCM_TRIGGER_STOP: 1270 - snd_azf3328_dbgplay("STOP %s\n", codec->name); 1261 + snd_azf3328_dbgcodec("STOP %s\n", codec->name); 1271 1262 1272 1263 if (is_playback_codec) { 1273 1264 /* mute WaveOut (avoid clicking during setup) */ ··· 1303 1294 ); 1304 1295 } 1305 1296 1306 - snd_azf3328_dbgplay("STOPPED %s\n", codec->name); 1297 + snd_azf3328_dbgcodec("STOPPED %s\n", codec->name); 1307 1298 break; 1308 1299 case SNDRV_PCM_TRIGGER_SUSPEND: 1309 - snd_azf3328_dbgplay("SUSPEND %s\n", codec->name); 1300 + snd_azf3328_dbgcodec("SUSPEND %s\n", codec->name); 1310 1301 /* make sure codec is stopped */ 1311 1302 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1312 1303 snd_azf3328_codec_inw( ··· 1321 1312 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); 1322 1313 break; 1323 1314 default: 1324 - printk(KERN_ERR "FIXME: unknown trigger mode!\n"); 1315 + snd_printk(KERN_ERR "FIXME: unknown trigger mode!\n"); 1325 1316 return -EINVAL; 1326 1317 } 1327 1318 ··· 1367 1358 /* calculate offset */ 1368 1359 result -= bufptr; 1369 1360 frmres = bytes_to_frames( substream->runtime, result); 1370 - snd_azf3328_dbgplay("%s @ 0x%8lx, frames %8ld\n", 1361 + snd_azf3328_dbgcodec("%s @ 0x%8lx, frames %8ld\n", 1371 1362 codec->name, result, frmres); 1372 1363 return frmres; 1373 1364 } ··· 1616 1607 static inline void 1617 1608 snd_azf3328_irq_log_unknown_type(u8 which) 1618 1609 { 1619 - snd_azf3328_dbgplay( 1610 + snd_azf3328_dbgcodec( 1620 1611 "azt3328: unknown IRQ type (%x) occurred, please report!\n", 1621 1612 which 1622 1613 ); ··· 1645 1636 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); 1646 1637 spin_unlock(&chip->reg_lock); 1647 1638 1648 - if ((chip->pcm[codec_type]) 1649 - && (chip->codecs[codec_type].substream)) { 1650 - snd_pcm_period_elapsed( 1651 - chip->codecs[codec_type].substream 1652 - ); 1653 - snd_azf3328_dbgplay("%s period done (#%x), @ %x\n", 1639 + if ((chip->pcm[codec_type]) && (codec->substream)) { 1640 + snd_pcm_period_elapsed(codec->substream); 1641 + snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", 1654 1642 codec->name, 1655 1643 which, 1656 1644 snd_azf3328_codec_inl( ··· 1666 1660 { 1667 1661 struct snd_azf3328 *chip = dev_id; 1668 1662 u8 status; 1669 - #if DEBUG_PLAY_REC 1663 + #if DEBUG_CODEC 1670 1664 static unsigned long irq_count; 1671 1665 #endif 1672 1666 ··· 1679 1673 )) 1680 1674 return IRQ_NONE; /* must be interrupt for another device */ 1681 1675 1682 - snd_azf3328_dbgplay( 1676 + snd_azf3328_dbgcodec( 1683 1677 "irq_count %ld! IDX_IO_IRQSTATUS %04x\n", 1684 1678 irq_count++ /* debug-only */, 1685 1679 status 1686 1680 ); 1687 1681 1688 1682 if (status & IRQ_TIMER) { 1689 - /* snd_azf3328_dbgplay("timer %ld\n", 1683 + /* snd_azf3328_dbgcodec("timer %ld\n", 1690 1684 snd_azf3328_codec_inl(chip, IDX_IO_TIMER_VALUE) 1691 1685 & TIMER_VALUE_MASK 1692 1686 ); */ ··· 1696 1690 spin_lock(&chip->reg_lock); 1697 1691 snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); 1698 1692 spin_unlock(&chip->reg_lock); 1699 - snd_azf3328_dbgplay("azt3328: timer IRQ\n"); 1693 + snd_azf3328_dbgcodec("azt3328: timer IRQ\n"); 1700 1694 } 1701 1695 1702 1696 if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) ··· 1712 1706 1713 1707 /* hmm, do we have to ack the IRQ here somehow? 1714 1708 * If so, then I don't know how yet... */ 1715 - snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n"); 1709 + snd_azf3328_dbgcodec("azt3328: MPU401 IRQ\n"); 1716 1710 } 1717 1711 return IRQ_HANDLED; 1718 1712 } ··· 2097 2091 2098 2092 outb(val, reg); 2099 2093 2100 - printk(KERN_ERR "reg %04x bit %d: %02x %02x %02x\n", 2094 + printk(KERN_DEBUG "reg %04x bit %d: %02x %02x %02x\n", 2101 2095 reg, bit, val, valoff, valon 2102 2096 ); 2103 2097 } ··· 2304 2298 2305 2299 card->private_data = chip; 2306 2300 2301 + /* chose to use MPU401_HW_AZT2320 ID instead of MPU401_HW_MPU401, 2302 + since our hardware ought to be similar, thus use same ID. */ 2307 2303 err = snd_mpu401_uart_new( 2308 - card, 0, MPU401_HW_MPU401, chip->mpu_io, MPU401_INFO_INTEGRATED, 2304 + card, 0, 2305 + MPU401_HW_AZT2320, chip->mpu_io, MPU401_INFO_INTEGRATED, 2309 2306 pci->irq, 0, &chip->rmidi 2310 2307 ); 2311 2308 if (err < 0) { ··· 2351 2342 goto out_err; 2352 2343 2353 2344 #ifdef MODULE 2354 - printk( 2345 + printk(KERN_INFO 2355 2346 "azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n" 2356 2347 "azt3328: Hardware was completely undocumented, unfortunately.\n" 2357 2348 "azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n" ··· 2386 2377 } 2387 2378 2388 2379 #ifdef CONFIG_PM 2380 + static inline void 2381 + snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) 2382 + { 2383 + unsigned reg; 2384 + 2385 + for (reg = 0; reg < count; ++reg) { 2386 + *saved_regs = inl(io_addr); 2387 + snd_azf3328_dbgpm("suspend: io 0x%04lx: 0x%08x\n", 2388 + io_addr, *saved_regs); 2389 + ++saved_regs; 2390 + io_addr += sizeof(*saved_regs); 2391 + } 2392 + } 2393 + 2389 2394 static int 2390 2395 snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) 2391 2396 { 2392 2397 struct snd_card *card = pci_get_drvdata(pci); 2393 2398 struct snd_azf3328 *chip = card->private_data; 2394 - unsigned reg; 2399 + u16 *saved_regs_ctrl_u16; 2395 2400 2396 2401 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 2397 2402 2398 2403 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); 2399 2404 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); 2400 2405 2401 - for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) 2402 - chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2); 2406 + snd_azf3328_suspend_regs(chip->mixer_io, 2407 + ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer); 2403 2408 2404 2409 /* make sure to disable master volume etc. to prevent looping sound */ 2405 2410 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); 2406 2411 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 2407 2412 2408 - for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg) 2409 - chip->saved_regs_ctrl[reg] = inw(chip->ctrl_io + reg * 2); 2413 + snd_azf3328_suspend_regs(chip->ctrl_io, 2414 + ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl); 2410 2415 2411 2416 /* manually store the one currently relevant write-only reg, too */ 2412 - chip->saved_regs_ctrl[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH; 2417 + saved_regs_ctrl_u16 = (u16 *)chip->saved_regs_ctrl; 2418 + saved_regs_ctrl_u16[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH; 2413 2419 2414 - for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg) 2415 - chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2); 2416 - for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg) 2417 - chip->saved_regs_mpu[reg] = inw(chip->mpu_io + reg * 2); 2418 - for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg) 2419 - chip->saved_regs_opl3[reg] = inw(chip->opl3_io + reg * 2); 2420 + snd_azf3328_suspend_regs(chip->game_io, 2421 + ARRAY_SIZE(chip->saved_regs_game), chip->saved_regs_game); 2422 + snd_azf3328_suspend_regs(chip->mpu_io, 2423 + ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu); 2424 + snd_azf3328_suspend_regs(chip->opl3_io, 2425 + ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3); 2420 2426 2421 2427 pci_disable_device(pci); 2422 2428 pci_save_state(pci); ··· 2439 2415 return 0; 2440 2416 } 2441 2417 2418 + static inline void 2419 + snd_azf3328_resume_regs(const u32 *saved_regs, 2420 + unsigned long io_addr, 2421 + unsigned count 2422 + ) 2423 + { 2424 + unsigned reg; 2425 + 2426 + for (reg = 0; reg < count; ++reg) { 2427 + outl(*saved_regs, io_addr); 2428 + snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n", 2429 + io_addr, *saved_regs, inl(io_addr)); 2430 + ++saved_regs; 2431 + io_addr += sizeof(*saved_regs); 2432 + } 2433 + } 2434 + 2442 2435 static int 2443 2436 snd_azf3328_resume(struct pci_dev *pci) 2444 2437 { 2445 2438 struct snd_card *card = pci_get_drvdata(pci); 2446 2439 const struct snd_azf3328 *chip = card->private_data; 2447 - unsigned reg; 2448 2440 2449 2441 pci_set_power_state(pci, PCI_D0); 2450 2442 pci_restore_state(pci); ··· 2472 2432 } 2473 2433 pci_set_master(pci); 2474 2434 2475 - for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg) 2476 - outw(chip->saved_regs_game[reg], chip->game_io + reg * 2); 2477 - for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg) 2478 - outw(chip->saved_regs_mpu[reg], chip->mpu_io + reg * 2); 2479 - for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg) 2480 - outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2); 2481 - for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) 2482 - outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2); 2483 - for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg) 2484 - outw(chip->saved_regs_ctrl[reg], chip->ctrl_io + reg * 2); 2435 + snd_azf3328_resume_regs(chip->saved_regs_game, chip->game_io, 2436 + ARRAY_SIZE(chip->saved_regs_game)); 2437 + snd_azf3328_resume_regs(chip->saved_regs_mpu, chip->mpu_io, 2438 + ARRAY_SIZE(chip->saved_regs_mpu)); 2439 + snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io, 2440 + ARRAY_SIZE(chip->saved_regs_opl3)); 2441 + 2442 + snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io, 2443 + ARRAY_SIZE(chip->saved_regs_mixer)); 2444 + 2445 + /* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02) 2446 + and IDX_MIXER_RESET (offset 0x00) get touched at the same time, 2447 + resulting in a mixer reset condition persisting until _after_ 2448 + master vol was restored. Thus master vol needs an extra restore. */ 2449 + outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2); 2450 + 2451 + snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io, 2452 + ARRAY_SIZE(chip->saved_regs_ctrl)); 2485 2453 2486 2454 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 2487 2455 return 0;
+11 -5
sound/pci/azt3328.h
··· 120 120 #define IDX_IO_IRQSTATUS 0x64 121 121 /* some IRQ bit in here might also be used to signal a power-management timer 122 122 * timeout, to request shutdown of the chip (e.g. AD1815JS has such a thing). 123 - * Some OPL3 hardware (e.g. in LM4560) has some special timer hardware which 124 - * can trigger an OPL3 timer IRQ, so maybe there's such a thing as well... */ 123 + * OPL3 hardware contains several timers which confusingly in most cases 124 + * are NOT routed to an IRQ, but some designs (e.g. LM4560) DO support that, 125 + * so I wouldn't be surprised at all to discover that AZF3328 126 + * supports that thing as well... */ 125 127 126 128 #define IRQ_PLAYBACK 0x0001 127 129 #define IRQ_RECORDING 0x0002 ··· 131 129 #define IRQ_GAMEPORT 0x0008 /* Interrupt of Digital(ly) Enhanced Game Port */ 132 130 #define IRQ_MPU401 0x0010 133 131 #define IRQ_TIMER 0x0020 /* DirectX timer */ 134 - #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly I2S port? */ 135 - #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly I2S port? */ 132 + #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly OPL3 timer? */ 133 + #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly OPL3 timer? */ 136 134 #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ 137 135 /* this is set to e.g. 0x3ff or 0x300, and writable; 138 136 * maybe some buffer limit, but I couldn't find out more, PU:0x00ff: */ ··· 195 193 /*** Gameport area port indices ***/ 196 194 /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ 197 195 #define AZF_IO_SIZE_GAME 0x08 198 - #define AZF_IO_SIZE_GAME_PM 0x06 196 + #define AZF_IO_SIZE_GAME_PM 0x06 199 197 200 198 enum { 201 199 AZF_GAME_LEGACY_IO_PORT = 0x200 ··· 276 274 #define AZF_IO_SIZE_MPU_PM 0x04 277 275 278 276 /*** OPL3 synth ***/ 277 + /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ 279 278 #define AZF_IO_SIZE_OPL3 0x08 280 279 #define AZF_IO_SIZE_OPL3_PM 0x06 281 280 /* hmm, given that a standard OPL3 has 4 registers only, ··· 335 332 /* driver internal flags */ 336 333 #define SET_CHAN_LEFT 1 337 334 #define SET_CHAN_RIGHT 2 335 + 336 + /* helper macro to align I/O port ranges to 32bit I/O width */ 337 + #define AZF_ALIGN(x) (((x) + 3) & (~3)) 338 338 339 339 #endif /* __SOUND_AZT3328_H */