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

[ALSA] AZT3328 driver update

Modules: AZT3328 driver

this is now an even much more reworked patch (#3) for my azt3328.c ALSA driver.
IOW I spent another 4 evenings to get the sequencer timer to work properly
(my head is still hurting) and do lots of other cleanups.

Note that despite the extensive sequencer timer additions, the driver object
is still only 2kB bigger than the previous version, due to those many
optimizations...

Changes in version #3:
- fully working ALSA sequencer timer support for the card's 1024000Hz
DirectX timer (downscaling adjustable via seqtimer_scaling module param)
- an insane amount of code optimizations
- many, many cleanups

Changes in version #2:
- FOUND the 1us DirectX timer area (yay!), made the code respect it
properly
- renamed some 'weird' mixer control names according to ControlNames.txt
- cleanup unneeded debug messages, reformatting
- improved I/O register documentation
- constified many more structs

Changes in version #1:
- improves/fixes some fatal playback/recording interaction
- improves IRQ handler performance (and actually fixes some weird code)
- coalesces some I/O accesses
- slightly improves I/O interface documentation
- improves/fixes logging
- defines out some less important debug code
- constifies some data

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

authored by

Andreas Mohr and committed by
Jaroslav Kysela
d91c64c8 fc207733

+729 -389
+657 -326
sound/pci/azt3328.c
··· 1 1 /* 2 2 * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). 3 - * Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com> 3 + * Copyright (C) 2002, 2005 by Andreas Mohr <andi AT lisas.de> 4 4 * 5 5 * Framework borrowed from Bart Hartgers's als4000.c. 6 6 * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), ··· 46 46 * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr?? 47 47 * - game port (legacy address support) 48 48 * - built-in General DirectX timer having a 20 bits counter 49 - * with 1us resolution (FIXME: where is it?) 49 + * with 1us resolution (see below!) 50 50 * - I2S serial port for external DAC 51 51 * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI 52 52 * - supports hardware volume control ··· 55 55 * required for Microsoft's logo compliance (FIXME: where?) 56 56 * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms 57 57 * 58 + * Note that this driver now is actually *better* than the Windows driver, 59 + * since it additionally supports the card's 1MHz DirectX timer - just try 60 + * the following snd-seq module parameters etc.: 61 + * - options snd-seq seq_default_timer_class=2 seq_default_timer_sclass=0 62 + * seq_default_timer_card=0 seq_client_load=1 seq_default_timer_device=0 63 + * seq_default_timer_subdevice=0 seq_default_timer_resolution=1000000 64 + * - "timidity -iAv -B2,8 -Os -EFreverb=0" 65 + * - "pmidi -p 128:0 jazz.mid" 66 + * 58 67 * Certain PCI versions of this card are susceptible to DMA traffic underruns 59 68 * in some systems (resulting in sound crackling/clicking/popping), 60 69 * probably because they don't have a DMA FIFO buffer or so. 61 70 * Overview (PCI ID/PCI subID/PCI rev.): 62 71 * - no DMA crackling on SiS735: 0x50DC/0x1801/16 63 72 * - unknown performance: 0x50DC/0x1801/10 64 - * 73 + * (well, it's not bad on an Athlon 1800 with now very optimized IRQ handler) 74 + * 65 75 * Crackling happens with VIA chipsets or, in my case, an SiS735, which is 66 76 * supposed to be very fast and supposed to get rid of crackling much 67 77 * better than a VIA, yet ironically I still get crackling, like many other ··· 86 76 * - Disable ACPI/power management/"Auto Detect RAM/PCI Clk" in BIOS 87 77 * 88 78 * BUGS 89 - * - when Ctrl-C'ing mpg321, the playback loops a bit 90 - * (premature DMA playback reset?) 91 - * - full-duplex sometimes breaks (IRQ management issues?). 92 - * Once even a spontaneous REBOOT happened!!! 79 + * - full-duplex might *still* be problematic, not fully tested recently 93 80 * 94 81 * TODO 95 82 * - test MPU401 MIDI playback etc. 96 - * - power management (CONFIG_PM). See e.g. intel8x0 or cs4281. 83 + * - power management. See e.g. intel8x0 or cs4281. 97 84 * This would be nice since the chip runs a bit hot, and it's *required* 98 - * anyway for proper ACPI power management. In other words: rest 99 - * assured that I *will* implement this very soon; as soon as Linux 2.5.x 100 - * has power management that's bugfree enough to work properly on my desktop. 85 + * anyway for proper ACPI power management. 101 86 * - figure out what all unknown port bits are responsible for 102 87 */ 103 88 ··· 113 108 #include <sound/initval.h> 114 109 #include "azt3328.h" 115 110 116 - MODULE_AUTHOR("Andreas Mohr <hw7oshyuv3001@sneakemail.com>"); 111 + MODULE_AUTHOR("Andreas Mohr <andi AT lisas.de>"); 117 112 MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)"); 118 113 MODULE_LICENSE("GPL"); 119 114 MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); ··· 127 122 #define DEBUG_MIXER 0 128 123 #define DEBUG_PLAY_REC 0 129 124 #define DEBUG_IO 0 125 + #define DEBUG_TIMER 0 130 126 #define MIXER_TESTING 0 131 127 132 128 #if DEBUG_MISC ··· 138 132 139 133 #if DEBUG_CALLS 140 134 #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args) 141 - #define snd_azf3328_dbgcallenter() printk(KERN_ERR "entering %s\n", __FUNCTION__) 142 - #define snd_azf3328_dbgcallleave() printk(KERN_ERR "leaving %s\n", __FUNCTION__) 135 + #define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__) 136 + #define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__) 143 137 #else 144 138 #define snd_azf3328_dbgcalls(format, args...) 145 139 #define snd_azf3328_dbgcallenter() ··· 158 152 #define snd_azf3328_dbgplay(format, args...) 159 153 #endif 160 154 161 - #if DEBUG_IO 162 - #define snd_azf3328_dbgio(chip, where) \ 163 - printk(KERN_ERR "%s: IDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQMASK %04x, IDX_IO_IRQSTATUS %04x\n", where, inw(chip->codec_port+IDX_IO_PLAY_FLAGS), inw(chip->codec_port+IDX_IO_PLAY_IRQMASK), inw(chip->codec_port+IDX_IO_IRQSTATUS)) 155 + #if DEBUG_MISC 156 + #define snd_azf3328_dbgtimer(format, args...) printk(KERN_ERR format, ##args) 164 157 #else 165 - #define snd_azf3328_dbgio(chip, where) 166 - #endif 167 - 158 + #define snd_azf3328_dbgtimer(format, args...) 159 + #endif 160 + 168 161 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 169 162 module_param_array(index, int, NULL, 0444); 170 163 MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard."); ··· 182 177 MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard."); 183 178 #endif 184 179 185 - typedef struct _snd_azf3328 azf3328_t; 180 + static int seqtimer_scaling = 128; 181 + module_param(seqtimer_scaling, int, 0444); 182 + MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); 186 183 187 - struct _snd_azf3328 { 188 - int irq; 189 - 184 + typedef struct _snd_azf3328 { 185 + /* often-used fields towards beginning, then grouped */ 190 186 unsigned long codec_port; 191 187 unsigned long io2_port; 192 188 unsigned long mpu_port; 193 189 unsigned long synth_port; 194 190 unsigned long mixer_port; 195 191 196 - #ifdef SUPPORT_JOYSTICK 197 - struct gameport *gameport; 198 - #endif 192 + spinlock_t reg_lock; 199 193 200 - struct pci_dev *pci; 201 - snd_card_t *card; 202 - 194 + snd_timer_t *timer; 195 + 203 196 snd_pcm_t *pcm; 204 - snd_rawmidi_t *rmidi; 205 197 snd_pcm_substream_t *playback_substream; 206 198 snd_pcm_substream_t *capture_substream; 207 199 unsigned int is_playing; 208 200 unsigned int is_recording; 209 201 210 - spinlock_t reg_lock; 211 - }; 202 + snd_card_t *card; 203 + snd_rawmidi_t *rmidi; 212 204 213 - static struct pci_device_id snd_azf3328_ids[] = { 205 + #ifdef SUPPORT_JOYSTICK 206 + struct gameport *gameport; 207 + #endif 208 + 209 + struct pci_dev *pci; 210 + int irq; 211 + } azf3328_t; 212 + 213 + static const struct pci_device_id snd_azf3328_ids[] = { 214 214 { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */ 215 215 { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */ 216 216 { 0, } ··· 223 213 224 214 MODULE_DEVICE_TABLE(pci, snd_azf3328_ids); 225 215 226 - static inline void snd_azf3328_io2_write(azf3328_t *chip, int reg, unsigned char value) 216 + static inline void 217 + snd_azf3328_codec_outb(const azf3328_t *chip, int reg, u8 value) 218 + { 219 + outb(value, chip->codec_port + reg); 220 + } 221 + 222 + static inline u8 223 + snd_azf3328_codec_inb(const azf3328_t *chip, int reg) 224 + { 225 + return inb(chip->codec_port + reg); 226 + } 227 + 228 + static inline void 229 + snd_azf3328_codec_outw(const azf3328_t *chip, int reg, u16 value) 230 + { 231 + outw(value, chip->codec_port + reg); 232 + } 233 + 234 + static inline u16 235 + snd_azf3328_codec_inw(const azf3328_t *chip, int reg) 236 + { 237 + return inw(chip->codec_port + reg); 238 + } 239 + 240 + static inline void 241 + snd_azf3328_codec_outl(const azf3328_t *chip, int reg, u32 value) 242 + { 243 + outl(value, chip->codec_port + reg); 244 + } 245 + 246 + static inline void 247 + snd_azf3328_io2_outb(const azf3328_t *chip, int reg, u8 value) 227 248 { 228 249 outb(value, chip->io2_port + reg); 229 250 } 230 251 231 - static inline unsigned char snd_azf3328_io2_read(azf3328_t *chip, int reg) 252 + static inline u8 253 + snd_azf3328_io2_inb(const azf3328_t *chip, int reg) 232 254 { 233 255 return inb(chip->io2_port + reg); 234 256 } 235 257 236 - static void snd_azf3328_mixer_write(azf3328_t *chip, int reg, unsigned long value, int type) 258 + static inline void 259 + snd_azf3328_mixer_outw(const azf3328_t *chip, int reg, u16 value) 237 260 { 238 - switch(type) { 239 - case WORD_VALUE: 240 - outw(value, chip->mixer_port + reg); 241 - break; 242 - case DWORD_VALUE: 243 - outl(value, chip->mixer_port + reg); 244 - break; 245 - case BYTE_VALUE: 246 - outb(value, chip->mixer_port + reg); 247 - break; 248 - } 261 + outw(value, chip->mixer_port + reg); 249 262 } 250 263 251 - static void snd_azf3328_mixer_set_mute(azf3328_t *chip, int reg, int do_mute) 264 + static inline u16 265 + snd_azf3328_mixer_inw(const azf3328_t *chip, int reg) 252 266 { 267 + return inw(chip->mixer_port + reg); 268 + } 269 + 270 + static void 271 + snd_azf3328_mixer_set_mute(const azf3328_t *chip, int reg, int do_mute) 272 + { 273 + unsigned long portbase = chip->mixer_port + reg + 1; 253 274 unsigned char oldval; 254 275 255 276 /* the mute bit is on the *second* (i.e. right) register of a 256 277 * left/right channel setting */ 257 - oldval = inb(chip->mixer_port + reg + 1); 278 + oldval = inb(portbase); 258 279 if (do_mute) 259 280 oldval |= 0x80; 260 281 else 261 282 oldval &= ~0x80; 262 - outb(oldval, chip->mixer_port + reg + 1); 283 + outb(oldval, portbase); 263 284 } 264 285 265 - static void snd_azf3328_mixer_write_volume_gradually(azf3328_t *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay) 286 + static void 287 + snd_azf3328_mixer_write_volume_gradually(const azf3328_t *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay) 266 288 { 289 + unsigned long portbase = chip->mixer_port + reg; 267 290 unsigned char curr_vol_left = 0, curr_vol_right = 0; 268 291 int left_done = 0, right_done = 0; 269 292 270 293 snd_azf3328_dbgcallenter(); 271 294 if (chan_sel & SET_CHAN_LEFT) 272 - curr_vol_left = inb(chip->mixer_port + reg + 1); 295 + curr_vol_left = inb(portbase + 1); 273 296 else 274 297 left_done = 1; 275 298 if (chan_sel & SET_CHAN_RIGHT) 276 - curr_vol_right = inb(chip->mixer_port + reg + 0); 299 + curr_vol_right = inb(portbase + 0); 277 300 else 278 301 right_done = 1; 279 302 ··· 327 284 curr_vol_left++; 328 285 else 329 286 left_done = 1; 330 - outb(curr_vol_left, chip->mixer_port + reg + 1); 287 + outb(curr_vol_left, portbase + 1); 331 288 } 332 289 if (!right_done) 333 290 { ··· 341 298 /* during volume change, the right channel is crackling 342 299 * somewhat more than the left channel, unfortunately. 343 300 * This seems to be a hardware issue. */ 344 - outb(curr_vol_right, chip->mixer_port + reg + 0); 301 + outb(curr_vol_right, portbase + 0); 345 302 } 346 303 if (delay) 347 304 mdelay(delay); ··· 363 320 } azf3328_mixer_reg_t; 364 321 365 322 #define COMPOSE_MIXER_REG(reg,lchan_shift,rchan_shift,mask,invert,stereo,enum_c) \ 366 - ((reg) | (lchan_shift << 8) | (rchan_shift << 12) | (mask << 16) | (invert << 24) | (stereo << 25) | (enum_c << 26)) 323 + ((reg) | (lchan_shift << 8) | (rchan_shift << 12) | \ 324 + (mask << 16) | \ 325 + (invert << 24) | \ 326 + (stereo << 25) | \ 327 + (enum_c << 26)) 367 328 368 329 static void snd_azf3328_mixer_reg_decode(azf3328_mixer_reg_t *r, unsigned long val) 369 330 { ··· 419 372 .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0, 0, 0, enum_c), \ 420 373 } 421 374 422 - static int snd_azf3328_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 375 + static int 376 + snd_azf3328_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 423 377 { 424 378 azf3328_mixer_reg_t reg; 425 379 426 380 snd_azf3328_dbgcallenter(); 427 381 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 428 - uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; 382 + uinfo->type = reg.mask == 1 ? 383 + SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; 429 384 uinfo->count = reg.stereo + 1; 430 385 uinfo->value.integer.min = 0; 431 386 uinfo->value.integer.max = reg.mask; ··· 435 386 return 0; 436 387 } 437 388 438 - static int snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 389 + static int 390 + snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 439 391 { 440 392 azf3328_t *chip = snd_kcontrol_chip(kcontrol); 441 393 azf3328_mixer_reg_t reg; ··· 445 395 snd_azf3328_dbgcallenter(); 446 396 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 447 397 448 - oreg = inw(chip->mixer_port + reg.reg); 398 + oreg = snd_azf3328_mixer_inw(chip, reg.reg); 449 399 val = (oreg >> reg.lchan_shift) & reg.mask; 450 400 if (reg.invert) 451 401 val = reg.mask - val; ··· 456 406 val = reg.mask - val; 457 407 ucontrol->value.integer.value[1] = val; 458 408 } 459 - snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx (shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n", reg.reg, oreg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo); 409 + snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx " 410 + "(shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n", 411 + reg.reg, oreg, 412 + ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], 413 + reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo); 460 414 snd_azf3328_dbgcallleave(); 461 415 return 0; 462 416 } 463 417 464 - static int snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 418 + static int 419 + snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 465 420 { 466 421 azf3328_t *chip = snd_kcontrol_chip(kcontrol); 467 422 azf3328_mixer_reg_t reg; ··· 474 419 475 420 snd_azf3328_dbgcallenter(); 476 421 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 477 - oreg = inw(chip->mixer_port + reg.reg); 422 + oreg = snd_azf3328_mixer_inw(chip, reg.reg); 478 423 val = ucontrol->value.integer.value[0] & reg.mask; 479 424 if (reg.invert) 480 425 val = reg.mask - val; ··· 488 433 nreg |= (val << reg.rchan_shift); 489 434 } 490 435 if (reg.mask >= 0x07) /* it's a volume control, so better take care */ 491 - snd_azf3328_mixer_write_volume_gradually(chip, reg.reg, nreg >> 8, nreg & 0xff, SET_CHAN_LEFT|SET_CHAN_RIGHT, 0); /* just set both channels, doesn't matter */ 436 + snd_azf3328_mixer_write_volume_gradually( 437 + chip, reg.reg, nreg >> 8, nreg & 0xff, 438 + /* just set both channels, doesn't matter */ 439 + SET_CHAN_LEFT|SET_CHAN_RIGHT, 440 + 0); 492 441 else 493 - outw(nreg, chip->mixer_port + reg.reg); 442 + snd_azf3328_mixer_outw(chip, reg.reg, nreg); 494 443 495 - snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n", reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], oreg, reg.lchan_shift, reg.rchan_shift, nreg, inw(chip->mixer_port + reg.reg)); 444 + snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, " 445 + "oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n", 446 + reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], 447 + oreg, reg.lchan_shift, reg.rchan_shift, 448 + nreg, snd_azf3328_mixer_inw(chip, reg.reg)); 496 449 snd_azf3328_dbgcallleave(); 497 450 return (nreg != oreg); 498 451 } 499 452 500 - static int snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 453 + static int 454 + snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 501 455 { 502 - azf3328_mixer_reg_t reg; 503 - static char *texts1[2] = { "ModemOut1", "ModemOut2" }; 504 - static char *texts2[2] = { "MonoSelectSource1", "MonoSelectSource2" }; 505 - static char *texts3[8] = { 506 - "Mic", "CD", "Video", "Aux", "Line", 507 - "Mix", "Mix Mono", "Phone" 456 + static const char * const texts1[] = { 457 + "ModemOut1", "ModemOut2" 458 + }; 459 + static const char * const texts2[] = { 460 + "MonoSelectSource1", "MonoSelectSource2" 461 + }; 462 + static const char * const texts3[] = { 463 + "Mic", "CD", "Video", "Aux", 464 + "Line", "Mix", "Mix Mono", "Phone" 508 465 }; 466 + azf3328_mixer_reg_t reg; 509 467 510 468 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 511 469 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ··· 539 471 return 0; 540 472 } 541 473 542 - static int snd_azf3328_get_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 474 + static int 475 + snd_azf3328_get_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 543 476 { 544 - azf3328_mixer_reg_t reg; 545 477 azf3328_t *chip = snd_kcontrol_chip(kcontrol); 478 + azf3328_mixer_reg_t reg; 546 479 unsigned short val; 547 480 548 481 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 549 - val = inw(chip->mixer_port + reg.reg); 482 + val = snd_azf3328_mixer_inw(chip, reg.reg); 550 483 if (reg.reg == IDX_MIXER_REC_SELECT) 551 484 { 552 485 ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); ··· 555 486 } 556 487 else 557 488 ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); 558 - snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1], reg.lchan_shift, reg.enum_c); 489 + 490 + snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", 491 + reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1], 492 + reg.lchan_shift, reg.enum_c); 559 493 return 0; 560 494 } 561 495 562 - static int snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 496 + static int 497 + snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 563 498 { 564 - azf3328_mixer_reg_t reg; 565 499 azf3328_t *chip = snd_kcontrol_chip(kcontrol); 500 + azf3328_mixer_reg_t reg; 566 501 unsigned int oreg, nreg, val; 567 502 568 503 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 569 - oreg = inw(chip->mixer_port + reg.reg); 504 + oreg = snd_azf3328_mixer_inw(chip, reg.reg); 570 505 val = oreg; 571 506 if (reg.reg == IDX_MIXER_REC_SELECT) 572 507 { ··· 587 514 val &= ~((reg.enum_c - 1) << reg.lchan_shift); 588 515 val |= (ucontrol->value.enumerated.item[0] << reg.lchan_shift); 589 516 } 590 - outw(val, chip->mixer_port + reg.reg); 517 + snd_azf3328_mixer_outw(chip, reg.reg, val); 591 518 nreg = val; 592 519 593 520 snd_azf3328_dbgmixer("put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg); 594 521 return (nreg != oreg); 595 522 } 596 523 597 - static snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = { 524 + static const snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = { 598 525 AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1), 599 526 AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1), 600 527 AZF3328_MIXER_SWITCH("Wave Playback Switch", IDX_MIXER_WAVEOUT, 15, 1), 601 528 AZF3328_MIXER_VOL_STEREO("Wave Playback Volume", IDX_MIXER_WAVEOUT, 0x1f, 1), 602 - AZF3328_MIXER_SWITCH("Wave Playback 3D Bypass", IDX_MIXER_ADVCTL2, 7, 1), 529 + AZF3328_MIXER_SWITCH("Wave 3D Bypass Playback Switch", IDX_MIXER_ADVCTL2, 7, 1), 603 530 AZF3328_MIXER_SWITCH("FM Playback Switch", IDX_MIXER_FMSYNTH, 15, 1), 604 531 AZF3328_MIXER_VOL_STEREO("FM Playback Volume", IDX_MIXER_FMSYNTH, 0x1f, 1), 605 532 AZF3328_MIXER_SWITCH("CD Playback Switch", IDX_MIXER_CDAUDIO, 15, 1), ··· 612 539 AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0), 613 540 AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1), 614 541 AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1), 615 - AZF3328_MIXER_SWITCH("PCBeep Playback Switch", IDX_MIXER_PCBEEP, 15, 1), 616 - AZF3328_MIXER_VOL_SPECIAL("PCBeep Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1), 542 + AZF3328_MIXER_SWITCH("PC Speaker Playback Switch", IDX_MIXER_PCBEEP, 15, 1), 543 + AZF3328_MIXER_VOL_SPECIAL("PC Speaker Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1), 617 544 AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1), 618 545 AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1), 619 546 AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1), ··· 626 553 AZF3328_MIXER_ENUM("Mono Select Source", IDX_MIXER_ADVCTL2, 2, 9), 627 554 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), 628 555 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), 629 - AZF3328_MIXER_SWITCH("3D Control - Toggle", IDX_MIXER_ADVCTL2, 13, 0), 630 - AZF3328_MIXER_VOL_SPECIAL("3D Control - Volume", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ 556 + AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), 557 + AZF3328_MIXER_VOL_SPECIAL("3D Control - Wide", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ 631 558 AZF3328_MIXER_VOL_SPECIAL("3D Control - Space", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ 632 559 #if MIXER_TESTING 633 560 AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0), ··· 649 576 #endif 650 577 }; 651 578 652 - #define AZF3328_INIT_VALUES (sizeof(snd_azf3328_init_values)/sizeof(unsigned int)/2) 653 - 654 - static unsigned int snd_azf3328_init_values[][2] = { 579 + static const u16 __devinitdata snd_azf3328_init_values[][2] = { 655 580 { IDX_MIXER_PLAY_MASTER, MIXER_MUTE_MASK|0x1f1f }, 656 581 { IDX_MIXER_MODEMOUT, MIXER_MUTE_MASK|0x1f1f }, 657 582 { IDX_MIXER_BASSTREBLE, 0x0000 }, ··· 665 594 { IDX_MIXER_REC_VOLUME, MIXER_MUTE_MASK|0x0707 }, 666 595 }; 667 596 668 - static int __devinit snd_azf3328_mixer_new(azf3328_t *chip) 597 + static int __devinit 598 + snd_azf3328_mixer_new(azf3328_t *chip) 669 599 { 670 600 snd_card_t *card; 671 - snd_kcontrol_new_t *sw; 601 + const snd_kcontrol_new_t *sw; 672 602 unsigned int idx; 673 603 int err; 674 604 ··· 679 607 card = chip->card; 680 608 681 609 /* mixer reset */ 682 - snd_azf3328_mixer_write(chip, IDX_MIXER_RESET, 0x0, WORD_VALUE); 610 + snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); 683 611 684 612 /* mute and zero volume channels */ 685 - for (idx = 0; idx < AZF3328_INIT_VALUES; idx++) { 686 - snd_azf3328_mixer_write(chip, snd_azf3328_init_values[idx][0], snd_azf3328_init_values[idx][1], WORD_VALUE); 613 + for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); idx++) { 614 + snd_azf3328_mixer_outw(chip, 615 + snd_azf3328_init_values[idx][0], 616 + snd_azf3328_init_values[idx][1]); 687 617 } 688 618 689 619 /* add mixer controls */ ··· 701 627 return 0; 702 628 } 703 629 704 - static int snd_azf3328_hw_params(snd_pcm_substream_t * substream, 630 + static int 631 + snd_azf3328_hw_params(snd_pcm_substream_t * substream, 705 632 snd_pcm_hw_params_t * hw_params) 706 633 { 707 634 int res; ··· 712 637 return res; 713 638 } 714 639 715 - static int snd_azf3328_hw_free(snd_pcm_substream_t * substream) 640 + static int 641 + snd_azf3328_hw_free(snd_pcm_substream_t * substream) 716 642 { 717 643 snd_azf3328_dbgcallenter(); 718 644 snd_pcm_lib_free_pages(substream); ··· 721 645 return 0; 722 646 } 723 647 724 - static void snd_azf3328_setfmt(azf3328_t *chip, 648 + static void 649 + snd_azf3328_setfmt(azf3328_t *chip, 725 650 unsigned int reg, 726 651 unsigned int bitrate, 727 652 unsigned int format_width, 728 653 unsigned int channels 729 654 ) 730 655 { 731 - unsigned int val = 0xff00; 656 + u16 val = 0xff00; 732 657 unsigned long flags; 733 658 734 659 snd_azf3328_dbgcallenter(); 735 660 switch (bitrate) { 736 - case 5512: val |= 0x0d; break; /* the AZF3328 names it "5510" for some strange reason */ 737 - case 6620: val |= 0x0b; break; 738 - case 8000: val |= 0x00; break; 739 - case 9600: val |= 0x08; break; 740 - case 11025: val |= 0x01; break; 741 - case 16000: val |= 0x02; break; 742 - case 22050: val |= 0x03; break; 743 - case 32000: val |= 0x04; break; 744 - case 44100: val |= 0x05; break; 745 - case 48000: val |= 0x06; break; 746 - case 64000: val |= 0x07; break; 661 + case 4000: val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break; 662 + case 4800: val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break; 663 + case 5512: val |= SOUNDFORMAT_FREQ_5510; break; /* the AZF3328 names it "5510" for some strange reason */ 664 + case 6620: val |= SOUNDFORMAT_FREQ_6620; break; 665 + case 8000: val |= SOUNDFORMAT_FREQ_8000; break; 666 + case 9600: val |= SOUNDFORMAT_FREQ_9600; break; 667 + case 11025: val |= SOUNDFORMAT_FREQ_11025; break; 668 + case 13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break; 669 + case 16000: val |= SOUNDFORMAT_FREQ_16000; break; 670 + case 22050: val |= SOUNDFORMAT_FREQ_22050; break; 671 + case 32000: val |= SOUNDFORMAT_FREQ_32000; break; 672 + case 44100: val |= SOUNDFORMAT_FREQ_44100; break; 673 + case 48000: val |= SOUNDFORMAT_FREQ_48000; break; 674 + case 66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break; 747 675 default: 748 676 snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); 749 - val |= 0x05; /* 44100 */ 677 + val |= SOUNDFORMAT_FREQ_44100; 750 678 break; 751 679 } 752 - /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) */ 753 - /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) */ 754 - /* val = 0xff0a; 47m30.599s (4764,891Hz; -> 4800Hz???) */ 755 - /* val = 0xff0c; 57m0.510s (4010,263Hz; -> 4000Hz???) */ 680 + /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */ 681 + /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */ 682 + /* val = 0xff0a; 47m30.599s (4764,891Hz; -> 4800Hz???) yup, 4803Hz */ 683 + /* val = 0xff0c; 57m0.510s (4010,263Hz; -> 4000Hz???) yup, 4003Hz */ 756 684 /* val = 0xff05; 5m11.556s (... -> 44100Hz) */ 757 685 /* val = 0xff03; 10m21.529s (21872,463Hz; -> 22050Hz???) */ 758 686 /* val = 0xff0f; 20m41.883s (10937,993Hz; -> 11025Hz???) */ 759 687 /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */ 760 688 /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */ 689 + 761 690 if (channels == 2) 762 691 val |= SOUNDFORMAT_FLAG_2CHANNELS; 763 692 ··· 772 691 spin_lock_irqsave(&chip->reg_lock, flags); 773 692 774 693 /* set bitrate/format */ 775 - outw(val, chip->codec_port+reg); 694 + snd_azf3328_codec_outw(chip, reg, val); 776 695 777 696 /* changing the bitrate/format settings switches off the 778 697 * audio output with an annoying click in case of 8/16bit format change ··· 782 701 * FIXME: does this have some side effects for full-duplex 783 702 * or other dramatic side effects? */ 784 703 if (reg == IDX_IO_PLAY_SOUNDFORMAT) /* only do it for playback */ 785 - outw(inw(chip->codec_port + IDX_IO_PLAY_FLAGS)|DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_PLAY_FLAGS); 704 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 705 + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | 706 + DMA_PLAY_SOMETHING1 | 707 + DMA_PLAY_SOMETHING2 | 708 + SOMETHING_ALMOST_ALWAYS_SET | 709 + DMA_EPILOGUE_SOMETHING | 710 + DMA_SOMETHING_ELSE 711 + ); 786 712 787 713 spin_unlock_irqrestore(&chip->reg_lock, flags); 788 714 snd_azf3328_dbgcallleave(); 789 715 } 790 716 791 - static void snd_azf3328_setdmaa(azf3328_t *chip, 717 + static void 718 + snd_azf3328_setdmaa(azf3328_t *chip, 792 719 long unsigned int addr, 793 720 unsigned int count, 794 721 unsigned int size, 795 722 int do_recording) 796 723 { 797 - long unsigned int addr1; 798 - long unsigned int addr2; 799 - unsigned int count1; 800 - unsigned int count2; 801 - unsigned long flags; 802 - int reg_offs = do_recording ? 0x20 : 0x00; 724 + unsigned long flags, portbase; 725 + unsigned int is_running; 803 726 804 727 snd_azf3328_dbgcallenter(); 805 - /* AZF3328 uses a two buffer pointer DMA playback approach */ 806 - if (!chip->is_playing) 728 + if (do_recording) 807 729 { 808 - addr1 = addr; 809 - addr2 = addr+(size/2); 810 - count1 = (size/2)-1; 811 - count2 = (size/2)-1; 812 - #if DEBUG_PLAY_REC 813 - snd_azf3328_dbgplay("setting dma: buf1 %08lx[%d], buf2 %08lx[%d]\n", addr1, count1, addr2, count2); 814 - #endif 730 + /* access capture registers, i.e. skip playback reg section */ 731 + portbase = chip->codec_port + 0x20; 732 + is_running = chip->is_recording; 733 + } 734 + else 735 + { 736 + /* access the playback register section */ 737 + portbase = chip->codec_port + 0x00; 738 + is_running = chip->is_playing; 739 + } 740 + 741 + /* AZF3328 uses a two buffer pointer DMA playback approach */ 742 + if (!is_running) 743 + { 744 + unsigned long addr_area2; 745 + unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ 746 + count_areas = size/2; 747 + addr_area2 = addr+count_areas; 748 + count_areas--; /* max. index */ 749 + snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas); 750 + 751 + /* build combined I/O buffer length word */ 752 + count_tmp = count_areas; 753 + count_areas |= (count_tmp << 16); 815 754 spin_lock_irqsave(&chip->reg_lock, flags); 816 - outl(addr1, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_START_1); 817 - outl(addr2, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_START_2); 818 - outw(count1, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_LEN_1); 819 - outw(count2, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_LEN_2); 755 + outl(addr, portbase + IDX_IO_PLAY_DMA_START_1); 756 + outl(addr_area2, portbase + IDX_IO_PLAY_DMA_START_2); 757 + outl(count_areas, portbase + IDX_IO_PLAY_DMA_LEN_1); 820 758 spin_unlock_irqrestore(&chip->reg_lock, flags); 821 759 } 822 760 snd_azf3328_dbgcallleave(); 823 761 } 824 762 825 - static int snd_azf3328_playback_prepare(snd_pcm_substream_t *substream) 763 + static int 764 + snd_azf3328_playback_prepare(snd_pcm_substream_t *substream) 826 765 { 827 766 #if 0 828 767 azf3328_t *chip = snd_pcm_substream_chip(substream); ··· 853 752 854 753 snd_azf3328_dbgcallenter(); 855 754 #if 0 856 - snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); 755 + snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, 756 + runtime->rate, 757 + snd_pcm_format_width(runtime->format), 758 + runtime->channels); 857 759 snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 0); 858 760 #endif 859 761 snd_azf3328_dbgcallleave(); 860 762 return 0; 861 763 } 862 764 863 - static int snd_azf3328_capture_prepare(snd_pcm_substream_t * substream) 765 + static int 766 + snd_azf3328_capture_prepare(snd_pcm_substream_t * substream) 864 767 { 865 768 #if 0 866 769 azf3328_t *chip = snd_pcm_substream_chip(substream); ··· 875 770 876 771 snd_azf3328_dbgcallenter(); 877 772 #if 0 878 - snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); 773 + snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, 774 + runtime->rate, 775 + snd_pcm_format_width(runtime->format), 776 + runtime->channels); 879 777 snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 1); 880 778 #endif 881 779 snd_azf3328_dbgcallleave(); 882 780 return 0; 883 781 } 884 782 885 - static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd) 783 + static int 784 + snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd) 886 785 { 887 786 azf3328_t *chip = snd_pcm_substream_chip(substream); 888 787 snd_pcm_runtime_t *runtime = substream->runtime; ··· 894 785 unsigned int status1; 895 786 896 787 snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd); 788 + 897 789 switch (cmd) { 898 790 case SNDRV_PCM_TRIGGER_START: 899 - 900 - snd_azf3328_dbgio(chip, "trigger1"); 791 + snd_azf3328_dbgplay("START PLAYBACK\n"); 901 792 902 793 /* mute WaveOut */ 903 794 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 904 795 905 - snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); 796 + snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, 797 + runtime->rate, 798 + snd_pcm_format_width(runtime->format), 799 + runtime->channels); 906 800 907 801 spin_lock(&chip->reg_lock); 908 802 /* stop playback */ 909 - status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS); 803 + status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); 910 804 status1 &= ~DMA_RESUME; 911 - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); 805 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 912 806 913 807 /* FIXME: clear interrupts or what??? */ 914 - outw(0xffff, chip->codec_port+IDX_IO_PLAY_IRQMASK); 808 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff); 915 809 spin_unlock(&chip->reg_lock); 916 810 917 - snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 0); 811 + snd_azf3328_setdmaa(chip, runtime->dma_addr, 812 + snd_pcm_lib_period_bytes(substream), 813 + snd_pcm_lib_buffer_bytes(substream), 814 + 0); 918 815 919 816 spin_lock(&chip->reg_lock); 920 817 #ifdef WIN9X 921 818 /* FIXME: enable playback/recording??? */ 922 819 status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; 923 - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); 820 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 924 821 925 822 /* start playback again */ 926 823 /* FIXME: what is this value (0x0010)??? */ 927 824 status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; 928 - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); 825 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 929 826 #else /* NT4 */ 930 - outw(0x00, chip->codec_port+IDX_IO_PLAY_FLAGS); 931 - outw(DMA_PLAY_SOMETHING1, chip->codec_port+IDX_IO_PLAY_FLAGS); 932 - outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_PLAY_FLAGS); 933 - outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_PLAY_FLAGS); 827 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 828 + 0x0000); 829 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 830 + DMA_PLAY_SOMETHING1); 831 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 832 + DMA_PLAY_SOMETHING1 | 833 + DMA_PLAY_SOMETHING2); 834 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 835 + DMA_RESUME | 836 + SOMETHING_ALMOST_ALWAYS_SET | 837 + DMA_EPILOGUE_SOMETHING | 838 + DMA_SOMETHING_ELSE); 934 839 #endif 935 840 spin_unlock(&chip->reg_lock); 936 841 937 842 /* now unmute WaveOut */ 938 843 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); 939 844 940 - snd_azf3328_dbgio(chip, "trigger2"); 941 845 chip->is_playing = 1; 846 + snd_azf3328_dbgplay("STARTED PLAYBACK\n"); 942 847 break; 943 - case SNDRV_PCM_TRIGGER_STOP: 848 + case SNDRV_PCM_TRIGGER_STOP: 849 + snd_azf3328_dbgplay("STOP PLAYBACK\n"); 850 + 944 851 /* mute WaveOut */ 945 852 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 946 853 947 854 spin_lock(&chip->reg_lock); 948 855 /* stop playback */ 949 - status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS); 856 + status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); 950 857 951 858 status1 &= ~DMA_RESUME; 952 - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); 859 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 953 860 861 + /* hmm, is this really required? we're resetting the same bit 862 + * immediately thereafter... */ 954 863 status1 |= DMA_PLAY_SOMETHING1; 955 - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); 864 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 956 865 957 866 status1 &= ~DMA_PLAY_SOMETHING1; 958 - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); 867 + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 959 868 spin_unlock(&chip->reg_lock); 960 869 961 870 /* now unmute WaveOut */ 962 871 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); 963 872 chip->is_playing = 0; 873 + snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); 964 874 break; 965 875 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 966 876 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); ··· 997 869 998 870 /* this is just analogous to playback; I'm not quite sure whether recording 999 871 * should actually be triggered like that */ 1000 - static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd) 872 + static int 873 + snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd) 1001 874 { 1002 875 azf3328_t *chip = snd_pcm_substream_chip(substream); 1003 876 snd_pcm_runtime_t *runtime = substream->runtime; ··· 1006 877 unsigned int status1; 1007 878 1008 879 snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd); 880 + 1009 881 switch (cmd) { 1010 882 case SNDRV_PCM_TRIGGER_START: 1011 883 1012 - snd_azf3328_dbgio(chip, "trigger1"); 884 + snd_azf3328_dbgplay("START CAPTURE\n"); 1013 885 1014 - snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); 886 + snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, 887 + runtime->rate, 888 + snd_pcm_format_width(runtime->format), 889 + runtime->channels); 1015 890 1016 891 spin_lock(&chip->reg_lock); 1017 892 /* stop recording */ 1018 - status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS); 893 + status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); 1019 894 status1 &= ~DMA_RESUME; 1020 - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); 895 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1021 896 1022 897 /* FIXME: clear interrupts or what??? */ 1023 - outw(0xffff, chip->codec_port+IDX_IO_REC_IRQMASK); 898 + snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff); 1024 899 spin_unlock(&chip->reg_lock); 1025 900 1026 - snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 1); 901 + snd_azf3328_setdmaa(chip, runtime->dma_addr, 902 + snd_pcm_lib_period_bytes(substream), 903 + snd_pcm_lib_buffer_bytes(substream), 904 + 1); 1027 905 1028 906 spin_lock(&chip->reg_lock); 1029 907 #ifdef WIN9X 1030 908 /* FIXME: enable playback/recording??? */ 1031 909 status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; 1032 - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); 910 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1033 911 1034 - /* start playback again */ 912 + /* start capture again */ 1035 913 /* FIXME: what is this value (0x0010)??? */ 1036 914 status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; 1037 - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); 915 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1038 916 #else 1039 - outw(0x00, chip->codec_port+IDX_IO_REC_FLAGS); 1040 - outw(DMA_PLAY_SOMETHING1, chip->codec_port+IDX_IO_REC_FLAGS); 1041 - outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_REC_FLAGS); 1042 - outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_REC_FLAGS); 917 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 918 + 0x0000); 919 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 920 + DMA_PLAY_SOMETHING1); 921 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 922 + DMA_PLAY_SOMETHING1 | 923 + DMA_PLAY_SOMETHING2); 924 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 925 + DMA_RESUME | 926 + SOMETHING_ALMOST_ALWAYS_SET | 927 + DMA_EPILOGUE_SOMETHING | 928 + DMA_SOMETHING_ELSE); 1043 929 #endif 1044 930 spin_unlock(&chip->reg_lock); 1045 931 1046 - snd_azf3328_dbgio(chip, "trigger2"); 1047 - chip->is_playing = 1; 932 + chip->is_recording = 1; 933 + snd_azf3328_dbgplay("STARTED CAPTURE\n"); 1048 934 break; 1049 935 case SNDRV_PCM_TRIGGER_STOP: 936 + snd_azf3328_dbgplay("STOP CAPTURE\n"); 937 + 1050 938 spin_lock(&chip->reg_lock); 1051 939 /* stop recording */ 1052 - status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS); 940 + status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); 1053 941 1054 942 status1 &= ~DMA_RESUME; 1055 - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); 943 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1056 944 1057 945 status1 |= DMA_PLAY_SOMETHING1; 1058 - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); 946 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1059 947 1060 948 status1 &= ~DMA_PLAY_SOMETHING1; 1061 - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); 949 + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1062 950 spin_unlock(&chip->reg_lock); 1063 951 1064 - chip->is_playing = 0; 952 + chip->is_recording = 0; 953 + snd_azf3328_dbgplay("STOPPED CAPTURE\n"); 1065 954 break; 1066 955 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1067 956 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); ··· 1095 948 return result; 1096 949 } 1097 950 1098 - static snd_pcm_uframes_t snd_azf3328_playback_pointer(snd_pcm_substream_t * substream) 951 + static snd_pcm_uframes_t 952 + snd_azf3328_playback_pointer(snd_pcm_substream_t * substream) 1099 953 { 1100 954 azf3328_t *chip = snd_pcm_substream_chip(substream); 1101 - unsigned long bufptr, playptr; 1102 - unsigned long result; 955 + unsigned long bufptr, result; 1103 956 snd_pcm_uframes_t frmres; 1104 957 1105 958 #ifdef QUERY_HARDWARE ··· 1107 960 #else 1108 961 bufptr = substream->runtime->dma_addr; 1109 962 #endif 1110 - playptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS); 963 + result = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS); 1111 964 1112 - result = playptr - bufptr; 1113 - frmres = bytes_to_frames( substream->runtime, result ); 1114 - snd_azf3328_dbgplay("result %lx, playptr %lx (base %x), frames %ld\n", result, playptr, substream->runtime->dma_addr, frmres); 965 + /* calculate offset */ 966 + result -= bufptr; 967 + frmres = bytes_to_frames( substream->runtime, result); 968 + snd_azf3328_dbgplay("PLAY @ 0x%8lx, frames %8ld\n", result, frmres); 1115 969 return frmres; 1116 970 } 1117 971 1118 - static snd_pcm_uframes_t snd_azf3328_capture_pointer(snd_pcm_substream_t * substream) 972 + static snd_pcm_uframes_t 973 + snd_azf3328_capture_pointer(snd_pcm_substream_t * substream) 1119 974 { 1120 975 azf3328_t *chip = snd_pcm_substream_chip(substream); 1121 - unsigned long bufptr, recptr; 1122 - unsigned long result; 976 + unsigned long bufptr, result; 1123 977 snd_pcm_uframes_t frmres; 1124 978 1125 979 #ifdef QUERY_HARDWARE ··· 1128 980 #else 1129 981 bufptr = substream->runtime->dma_addr; 1130 982 #endif 1131 - recptr = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS); 983 + result = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS); 1132 984 1133 - result = recptr - bufptr; 1134 - frmres = bytes_to_frames( substream->runtime, result ); 1135 - snd_azf3328_dbgplay("result %lx, rec ptr %lx (base %x), frames %ld\n", result, recptr, substream->runtime->dma_addr, frmres); 985 + /* calculate offset */ 986 + result -= bufptr; 987 + frmres = bytes_to_frames( substream->runtime, result); 988 + snd_azf3328_dbgplay("REC @ 0x%8lx, frames %8ld\n", result, frmres); 1136 989 return frmres; 1137 990 } 1138 991 1139 - static irqreturn_t snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) 992 + static irqreturn_t 993 + snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) 1140 994 { 1141 995 azf3328_t *chip = dev_id; 1142 - unsigned int status, which; 1143 - static unsigned long count; 996 + u8 status, which; 997 + static unsigned long irq_count; 1144 998 1145 - status = inw(chip->codec_port+IDX_IO_IRQSTATUS); 999 + status = snd_azf3328_codec_inb(chip, IDX_IO_IRQSTATUS); 1146 1000 1147 1001 /* fast path out, to ease interrupt sharing */ 1148 - if (!(status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_MPU401|IRQ_SOMEIRQ))) 1002 + if (!(status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_MPU401|IRQ_TIMER))) 1149 1003 return IRQ_NONE; /* must be interrupt for another device */ 1150 1004 1151 - snd_azf3328_dbgplay("Interrupt %ld!\nIDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQMASK %04x, IDX_IO_IRQSTATUS %04x\n", count, inw(chip->codec_port+IDX_IO_PLAY_FLAGS), inw(chip->codec_port+IDX_IO_PLAY_IRQMASK), inw(chip->codec_port+IDX_IO_IRQSTATUS)); 1005 + snd_azf3328_dbgplay("Interrupt %ld!\nIDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n", 1006 + irq_count, 1007 + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS), 1008 + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), 1009 + status); 1152 1010 1011 + if (status & IRQ_TIMER) 1012 + { 1013 + /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ 1014 + if (chip->timer) 1015 + snd_timer_interrupt(chip->timer, chip->timer->sticks); 1016 + /* ACK timer */ 1017 + spin_lock(&chip->reg_lock); 1018 + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); 1019 + spin_unlock(&chip->reg_lock); 1020 + snd_azf3328_dbgplay("azt3328: timer IRQ\n"); 1021 + } 1153 1022 if (status & IRQ_PLAYBACK) 1154 1023 { 1155 1024 spin_lock(&chip->reg_lock); 1156 - which = inw(chip->codec_port+IDX_IO_PLAY_IRQMASK); 1157 - if (which & IRQ_FINISHED_PLAYBUF_1) 1158 - /* ack IRQ */ 1159 - outw(which | IRQ_FINISHED_PLAYBUF_1, chip->codec_port+IDX_IO_PLAY_IRQMASK); 1160 - if (which & IRQ_FINISHED_PLAYBUF_2) 1161 - /* ack IRQ */ 1162 - outw(which | IRQ_FINISHED_PLAYBUF_2, chip->codec_port+IDX_IO_PLAY_IRQMASK); 1163 - if (which & IRQ_PLAY_SOMETHING) 1164 - { 1165 - snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); 1166 - } 1025 + which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); 1026 + /* ack all IRQ types immediately */ 1027 + snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); 1028 + spin_unlock(&chip->reg_lock); 1029 + 1167 1030 if (chip->pcm && chip->playback_substream) 1168 1031 { 1169 - snd_azf3328_dbgplay("which %x, playptr %lx\n", which, inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); 1170 1032 snd_pcm_period_elapsed(chip->playback_substream); 1171 - snd_azf3328_dbgplay("period done, playptr %lx.\n", inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); 1033 + snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", 1034 + which, 1035 + inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); 1172 1036 } 1173 1037 else 1174 1038 snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); 1175 - spin_unlock(&chip->reg_lock); 1039 + if (which & IRQ_PLAY_SOMETHING) 1040 + snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); 1176 1041 } 1177 1042 if (status & IRQ_RECORDING) 1178 1043 { 1179 1044 spin_lock(&chip->reg_lock); 1180 - which = inw(chip->codec_port+IDX_IO_REC_IRQMASK); 1181 - if (which & IRQ_FINISHED_RECBUF_1) 1182 - /* ack interrupt */ 1183 - outw(which | IRQ_FINISHED_RECBUF_1, chip->codec_port+IDX_IO_REC_IRQMASK); 1184 - if (which & IRQ_FINISHED_RECBUF_2) 1185 - /* ack interrupt */ 1186 - outw(which | IRQ_FINISHED_RECBUF_2, chip->codec_port+IDX_IO_REC_IRQMASK); 1187 - if (which & IRQ_REC_SOMETHING) 1188 - { 1189 - snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); 1190 - } 1045 + which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); 1046 + /* ack all IRQ types immediately */ 1047 + snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); 1048 + spin_unlock(&chip->reg_lock); 1049 + 1191 1050 if (chip->pcm && chip->capture_substream) 1192 1051 { 1193 - snd_azf3328_dbgplay("which %x, recptr %lx\n", which, inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); 1194 - spin_unlock(&chip->reg_lock); 1195 1052 snd_pcm_period_elapsed(chip->capture_substream); 1196 - spin_lock(&chip->reg_lock); 1197 - snd_azf3328_dbgplay("period done, recptr %lx.\n", inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); 1053 + snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", 1054 + which, 1055 + inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); 1198 1056 } 1199 - spin_unlock(&chip->reg_lock); 1057 + else 1058 + snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); 1059 + if (which & IRQ_REC_SOMETHING) 1060 + snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); 1200 1061 } 1062 + /* MPU401 has less critical IRQ requirements 1063 + * than timer and playback/recording, right? */ 1201 1064 if (status & IRQ_MPU401) 1065 + { 1202 1066 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); 1203 - if (status & IRQ_SOMEIRQ) 1204 - snd_azf3328_dbgplay("azt3328: unknown IRQ type occurred, please report!\n"); 1205 - count++; 1067 + 1068 + /* hmm, do we have to ack the IRQ here somehow? 1069 + * If so, then I don't know how... */ 1070 + snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n"); 1071 + } 1072 + irq_count++; 1206 1073 return IRQ_HANDLED; 1207 1074 } 1208 1075 1209 1076 /*****************************************************************/ 1210 1077 1211 - static snd_pcm_hardware_t snd_azf3328_playback = 1078 + static const snd_pcm_hardware_t snd_azf3328_playback = 1212 1079 { 1213 1080 /* FIXME!! Correct? */ 1214 - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 1215 - SNDRV_PCM_INFO_MMAP_VALID), 1216 - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | 1217 - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, 1218 - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_KNOT, 1219 - .rate_min = 5512, 1220 - .rate_max = 64000, 1081 + .info = SNDRV_PCM_INFO_MMAP | 1082 + SNDRV_PCM_INFO_INTERLEAVED | 1083 + SNDRV_PCM_INFO_MMAP_VALID, 1084 + .formats = SNDRV_PCM_FMTBIT_S8 | 1085 + SNDRV_PCM_FMTBIT_U8 | 1086 + SNDRV_PCM_FMTBIT_S16_LE | 1087 + SNDRV_PCM_FMTBIT_U16_LE, 1088 + .rates = SNDRV_PCM_RATE_5512 | 1089 + SNDRV_PCM_RATE_8000_48000 | 1090 + SNDRV_PCM_RATE_KNOT, 1091 + .rate_min = 4000, 1092 + .rate_max = 66200, 1221 1093 .channels_min = 1, 1222 1094 .channels_max = 2, 1223 1095 .buffer_bytes_max = 65536, ··· 1251 1083 .fifo_size = 0, 1252 1084 }; 1253 1085 1254 - static snd_pcm_hardware_t snd_azf3328_capture = 1086 + static const snd_pcm_hardware_t snd_azf3328_capture = 1255 1087 { 1256 1088 /* FIXME */ 1257 - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 1258 - SNDRV_PCM_INFO_MMAP_VALID), 1259 - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | 1260 - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, 1261 - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_KNOT, 1262 - .rate_min = 5512, 1263 - .rate_max = 64000, 1089 + .info = SNDRV_PCM_INFO_MMAP | 1090 + SNDRV_PCM_INFO_INTERLEAVED | 1091 + SNDRV_PCM_INFO_MMAP_VALID, 1092 + .formats = SNDRV_PCM_FMTBIT_S8 | 1093 + SNDRV_PCM_FMTBIT_U8 | 1094 + SNDRV_PCM_FMTBIT_S16_LE | 1095 + SNDRV_PCM_FMTBIT_U16_LE, 1096 + .rates = SNDRV_PCM_RATE_5512 | 1097 + SNDRV_PCM_RATE_8000_48000 | 1098 + SNDRV_PCM_RATE_KNOT, 1099 + .rate_min = 4000, 1100 + .rate_max = 66200, 1264 1101 .channels_min = 1, 1265 1102 .channels_max = 2, 1266 1103 .buffer_bytes_max = 65536, ··· 1278 1105 1279 1106 1280 1107 static unsigned int snd_azf3328_fixed_rates[] = { 1281 - 5512, 6620, 8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000, 64000 1282 - }; 1108 + 4000, 4800, 5512, 6620, 8000, 9600, 11025, 13240, 16000, 22050, 32000, 1109 + 44100, 48000, 66200 }; 1283 1110 static snd_pcm_hw_constraint_list_t snd_azf3328_hw_constraints_rates = { 1284 1111 .count = ARRAY_SIZE(snd_azf3328_fixed_rates), 1285 1112 .list = snd_azf3328_fixed_rates, ··· 1288 1115 1289 1116 /*****************************************************************/ 1290 1117 1291 - static int snd_azf3328_playback_open(snd_pcm_substream_t * substream) 1118 + static int 1119 + snd_azf3328_playback_open(snd_pcm_substream_t * substream) 1292 1120 { 1293 1121 azf3328_t *chip = snd_pcm_substream_chip(substream); 1294 1122 snd_pcm_runtime_t *runtime = substream->runtime; ··· 1303 1129 return 0; 1304 1130 } 1305 1131 1306 - static int snd_azf3328_capture_open(snd_pcm_substream_t * substream) 1132 + static int 1133 + snd_azf3328_capture_open(snd_pcm_substream_t * substream) 1307 1134 { 1308 1135 azf3328_t *chip = snd_pcm_substream_chip(substream); 1309 1136 snd_pcm_runtime_t *runtime = substream->runtime; ··· 1318 1143 return 0; 1319 1144 } 1320 1145 1321 - static int snd_azf3328_playback_close(snd_pcm_substream_t * substream) 1146 + static int 1147 + snd_azf3328_playback_close(snd_pcm_substream_t * substream) 1322 1148 { 1323 1149 azf3328_t *chip = snd_pcm_substream_chip(substream); 1324 1150 ··· 1330 1154 return 0; 1331 1155 } 1332 1156 1333 - static int snd_azf3328_capture_close(snd_pcm_substream_t * substream) 1157 + static int 1158 + snd_azf3328_capture_close(snd_pcm_substream_t * substream) 1334 1159 { 1335 1160 azf3328_t *chip = snd_pcm_substream_chip(substream); 1336 1161 ··· 1365 1188 .pointer = snd_azf3328_capture_pointer 1366 1189 }; 1367 1190 1368 - static void snd_azf3328_pcm_free(snd_pcm_t *pcm) 1191 + static void 1192 + snd_azf3328_pcm_free(snd_pcm_t *pcm) 1369 1193 { 1370 1194 azf3328_t *chip = pcm->private_data; 1371 1195 chip->pcm = NULL; 1372 1196 snd_pcm_lib_preallocate_free_for_all(pcm); 1373 1197 } 1374 1198 1375 - static int __devinit snd_azf3328_pcm(azf3328_t *chip, int device) 1199 + static int __devinit 1200 + snd_azf3328_pcm(azf3328_t *chip, int device) 1376 1201 { 1377 1202 snd_pcm_t *pcm; 1378 1203 int err; ··· 1401 1222 /******************************************************************/ 1402 1223 1403 1224 #ifdef SUPPORT_JOYSTICK 1404 - static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev) 1225 + static int __devinit 1226 + snd_azf3328_config_joystick(azf3328_t *chip, int dev) 1405 1227 { 1406 1228 struct gameport *gp; 1407 1229 struct resource *r; ··· 1428 1248 gp->io = 0x200; 1429 1249 gameport_set_port_data(gp, r); 1430 1250 1431 - snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, 1432 - snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY); 1251 + snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR, 1252 + snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY); 1433 1253 1434 1254 gameport_register_port(chip->gameport); 1435 1255 1436 1256 return 0; 1437 1257 } 1438 1258 1439 - static void snd_azf3328_free_joystick(azf3328_t *chip) 1259 + static void 1260 + snd_azf3328_free_joystick(azf3328_t *chip) 1440 1261 { 1441 1262 if (chip->gameport) { 1442 1263 struct resource *r = gameport_get_port_data(chip->gameport); ··· 1445 1264 gameport_unregister_port(chip->gameport); 1446 1265 chip->gameport = NULL; 1447 1266 /* disable gameport */ 1448 - snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, 1449 - snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); 1267 + snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR, 1268 + snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); 1450 1269 release_and_free_resource(r); 1451 1270 } 1452 1271 } 1453 1272 #else 1454 - static inline int snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; } 1455 - static inline void snd_azf3328_free_joystick(azf3328_t *chip) { } 1273 + static inline int 1274 + snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; } 1275 + static inline void 1276 + snd_azf3328_free_joystick(azf3328_t *chip) { } 1456 1277 #endif 1457 1278 1458 1279 /******************************************************************/ 1459 1280 1460 - static int snd_azf3328_free(azf3328_t *chip) 1281 + static int 1282 + snd_azf3328_free(azf3328_t *chip) 1461 1283 { 1462 1284 if (chip->irq < 0) 1463 1285 goto __end_hw; 1464 1286 1465 1287 /* reset (close) mixer */ 1466 1288 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); /* first mute master volume */ 1467 - snd_azf3328_mixer_write(chip, IDX_MIXER_RESET, 0x0, WORD_VALUE); 1289 + snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); 1468 1290 1469 - /* interrupt setup - mask everything */ 1470 - /* FIXME */ 1291 + /* interrupt setup - mask everything (FIXME!) */ 1292 + /* well, at least we know how to disable the timer IRQ */ 1293 + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00); 1471 1294 1472 1295 synchronize_irq(chip->irq); 1473 - __end_hw: 1296 + __end_hw: 1474 1297 snd_azf3328_free_joystick(chip); 1475 1298 if (chip->irq >= 0) 1476 1299 free_irq(chip->irq, (void *)chip); ··· 1485 1300 return 0; 1486 1301 } 1487 1302 1488 - static int snd_azf3328_dev_free(snd_device_t *device) 1303 + static int 1304 + snd_azf3328_dev_free(snd_device_t *device) 1489 1305 { 1490 1306 azf3328_t *chip = device->device_data; 1491 1307 return snd_azf3328_free(chip); 1492 1308 } 1493 1309 1310 + /******************************************************************/ 1311 + 1312 + /*** NOTE: the physical timer resolution actually is 1024000 ticks per second, 1313 + *** but announcing those attributes to user-space would make programs 1314 + *** configure the timer to a 1 tick value, resulting in an absolutely fatal 1315 + *** timer IRQ storm. 1316 + *** Thus I chose to announce a down-scaled virtual timer to the outside and 1317 + *** calculate real timer countdown values internally. 1318 + *** (the scale factor can be set via module parameter "seqtimer_scaling"). 1319 + ***/ 1320 + 1321 + static int 1322 + snd_azf3328_timer_start(snd_timer_t *timer) 1323 + { 1324 + azf3328_t *chip; 1325 + unsigned long flags; 1326 + unsigned int delay; 1327 + 1328 + snd_azf3328_dbgcallenter(); 1329 + chip = snd_timer_chip(timer); 1330 + delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; 1331 + if (delay < 49) 1332 + { 1333 + /* uhoh, that's not good, since user-space won't know about 1334 + * this timing tweak 1335 + * (we need to do it to avoid a lockup, though) */ 1336 + 1337 + snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay); 1338 + delay = 49; /* minimum time is 49 ticks */ 1339 + } 1340 + snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay); 1341 + delay |= TIMER_ENABLE_COUNTDOWN | TIMER_ENABLE_IRQ; 1342 + spin_lock_irqsave(&chip->reg_lock, flags); 1343 + snd_azf3328_codec_outl(chip, IDX_IO_TIMER_VALUE, delay); 1344 + spin_unlock_irqrestore(&chip->reg_lock, flags); 1345 + snd_azf3328_dbgcallleave(); 1346 + return 0; 1347 + } 1348 + 1349 + static int 1350 + snd_azf3328_timer_stop(snd_timer_t *timer) 1351 + { 1352 + azf3328_t *chip; 1353 + unsigned long flags; 1354 + 1355 + snd_azf3328_dbgcallenter(); 1356 + chip = snd_timer_chip(timer); 1357 + spin_lock_irqsave(&chip->reg_lock, flags); 1358 + /* disable timer countdown and interrupt */ 1359 + /* FIXME: should we write TIMER_ACK_IRQ here? */ 1360 + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); 1361 + spin_unlock_irqrestore(&chip->reg_lock, flags); 1362 + snd_azf3328_dbgcallleave(); 1363 + return 0; 1364 + } 1365 + 1366 + 1367 + static int 1368 + snd_azf3328_timer_precise_resolution(snd_timer_t *timer, 1369 + unsigned long *num, unsigned long *den) 1370 + { 1371 + snd_azf3328_dbgcallenter(); 1372 + *num = 1; 1373 + *den = 1024000 / seqtimer_scaling; 1374 + snd_azf3328_dbgcallleave(); 1375 + return 0; 1376 + } 1377 + 1378 + static struct _snd_timer_hardware snd_azf3328_timer_hw = { 1379 + .flags = SNDRV_TIMER_HW_AUTO, 1380 + .resolution = 977, /* 1000000/1024000 = 0.9765625us */ 1381 + .ticks = 1024000, /* max tick count, defined by the value register; actually it's not 1024000, but 1048576, but we don't care */ 1382 + .start = snd_azf3328_timer_start, 1383 + .stop = snd_azf3328_timer_stop, 1384 + .precise_resolution = snd_azf3328_timer_precise_resolution, 1385 + }; 1386 + 1387 + static int __devinit 1388 + snd_azf3328_timer(azf3328_t *chip, int device) 1389 + { 1390 + snd_timer_t *timer = NULL; 1391 + snd_timer_id_t tid; 1392 + int err; 1393 + 1394 + snd_azf3328_dbgcallenter(); 1395 + tid.dev_class = SNDRV_TIMER_CLASS_CARD; 1396 + tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; 1397 + tid.card = chip->card->number; 1398 + tid.device = device; 1399 + tid.subdevice = 0; 1400 + 1401 + snd_azf3328_timer_hw.resolution *= seqtimer_scaling; 1402 + snd_azf3328_timer_hw.ticks /= seqtimer_scaling; 1403 + if ((err = snd_timer_new(chip->card, "AZF3328", &tid, &timer)) < 0) { 1404 + goto out; 1405 + } 1406 + 1407 + strcpy(timer->name, "AZF3328 timer"); 1408 + timer->private_data = chip; 1409 + timer->hw = snd_azf3328_timer_hw; 1410 + 1411 + chip->timer = timer; 1412 + 1413 + err = 0; 1414 + 1415 + out: 1416 + snd_azf3328_dbgcallleave(); 1417 + return err; 1418 + } 1419 + 1420 + /******************************************************************/ 1421 + 1494 1422 #if 0 1495 1423 /* check whether a bit can be modified */ 1496 - static void snd_azf3328_test_bit(unsigned int reg, int bit) 1424 + static void 1425 + snd_azf3328_test_bit(unsigned int reg, int bit) 1497 1426 { 1498 1427 unsigned char val, valoff, valon; 1499 1428 ··· 1625 1326 } 1626 1327 #endif 1627 1328 1628 - static int __devinit snd_azf3328_create(snd_card_t * card, 1329 + static void 1330 + snd_azf3328_debug_show_ports(const azf3328_t *chip) 1331 + { 1332 + #if DEBUG_MISC 1333 + u16 tmp; 1334 + 1335 + snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq); 1336 + 1337 + snd_azf3328_dbgmisc("io2 %02x %02x %02x %02x %02x %02x\n", snd_azf3328_io2_inb(chip, 0), snd_azf3328_io2_inb(chip, 1), snd_azf3328_io2_inb(chip, 2), snd_azf3328_io2_inb(chip, 3), snd_azf3328_io2_inb(chip, 4), snd_azf3328_io2_inb(chip, 5)); 1338 + 1339 + for (tmp=0; tmp <= 0x01; tmp += 1) 1340 + snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp)); 1341 + 1342 + for (tmp = 0; tmp <= 0x6E; tmp += 2) 1343 + snd_azf3328_dbgmisc("0x%02x: 0x%04x\n", tmp, snd_azf3328_codec_inb(chip, tmp)); 1344 + #endif 1345 + } 1346 + 1347 + static int __devinit 1348 + snd_azf3328_create(snd_card_t * card, 1629 1349 struct pci_dev *pci, 1630 1350 unsigned long device_type, 1631 1351 azf3328_t ** rchip) ··· 1663 1345 1664 1346 chip = kzalloc(sizeof(*chip), GFP_KERNEL); 1665 1347 if (chip == NULL) { 1666 - pci_disable_device(pci); 1667 - return -ENOMEM; 1348 + err = -ENOMEM; 1349 + goto out_err; 1668 1350 } 1669 1351 spin_lock_init(&chip->reg_lock); 1670 1352 chip->card = card; ··· 1675 1357 if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || 1676 1358 pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { 1677 1359 snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); 1678 - pci_disable_device(pci); 1679 - return -ENXIO; 1360 + err = -ENXIO; 1361 + goto out_err; 1680 1362 } 1681 1363 1682 1364 if ((err = pci_request_regions(pci, "Aztech AZF3328")) < 0) { 1683 - kfree(chip); 1684 - pci_disable_device(pci); 1685 - return err; 1365 + goto out_err; 1686 1366 } 1687 1367 1688 1368 chip->codec_port = pci_resource_start(pci, 0); 1689 - chip->io2_port = pci_resource_start(pci, 1); 1690 - chip->mpu_port = pci_resource_start(pci, 2); 1369 + chip->io2_port = pci_resource_start(pci, 1); 1370 + chip->mpu_port = pci_resource_start(pci, 2); 1691 1371 chip->synth_port = pci_resource_start(pci, 3); 1692 1372 chip->mixer_port = pci_resource_start(pci, 4); 1693 1373 1694 1374 if (request_irq(pci->irq, snd_azf3328_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { 1695 1375 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); 1696 - snd_azf3328_free(chip); 1697 - return -EBUSY; 1376 + err = -EBUSY; 1377 + goto out_err; 1698 1378 } 1699 1379 chip->irq = pci->irq; 1700 1380 pci_set_master(pci); 1701 1381 synchronize_irq(chip->irq); 1702 1382 1703 - snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq); 1704 - 1705 - snd_azf3328_dbgmisc("io2 %02x %02x %02x %02x %02x %02x\n", snd_azf3328_io2_read(chip, 0), snd_azf3328_io2_read(chip, 1), snd_azf3328_io2_read(chip, 2), snd_azf3328_io2_read(chip, 3), snd_azf3328_io2_read(chip, 4), snd_azf3328_io2_read(chip, 5)); 1706 - 1707 - for (tmp=0; tmp <= 0x01; tmp += 1) 1708 - snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp)); 1709 - 1383 + snd_azf3328_debug_show_ports(chip); 1384 + 1710 1385 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 1711 - snd_azf3328_free(chip); 1712 - return err; 1386 + goto out_err; 1713 1387 } 1714 1388 1715 1389 /* create mixer interface & switches */ 1716 1390 if ((err = snd_azf3328_mixer_new(chip)) < 0) 1717 - return err; 1391 + goto out_err; 1718 1392 1719 1393 #if 0 1720 1394 /* set very low bitrate to reduce noise and power consumption? */ ··· 1714 1404 #endif 1715 1405 1716 1406 /* standard chip init stuff */ 1717 - spin_lock_irq(&chip->reg_lock); 1718 - outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_PLAY_FLAGS); 1719 - outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_SOMETHING_FLAGS); 1720 - outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_REC_FLAGS); 1721 - outb(0x0, chip->codec_port + IDX_IO_IRQ63H); 1407 + /* default IRQ init value */ 1408 + tmp = DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; 1722 1409 1410 + spin_lock_irq(&chip->reg_lock); 1411 + snd_azf3328_codec_outb(chip, IDX_IO_PLAY_FLAGS, tmp); 1412 + snd_azf3328_codec_outb(chip, IDX_IO_REC_FLAGS, tmp); 1413 + snd_azf3328_codec_outb(chip, IDX_IO_SOMETHING_FLAGS, tmp); 1414 + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00); /* disable timer */ 1723 1415 spin_unlock_irq(&chip->reg_lock); 1724 1416 1725 1417 snd_card_set_dev(card, &pci->dev); 1726 1418 1727 1419 *rchip = chip; 1728 - return 0; 1420 + 1421 + err = 0; 1422 + goto out; 1423 + 1424 + out_err: 1425 + if (chip) 1426 + snd_azf3328_free(chip); 1427 + pci_disable_device(pci); 1428 + 1429 + out: 1430 + return err; 1729 1431 } 1730 1432 1731 - static int __devinit snd_azf3328_probe(struct pci_dev *pci, 1732 - const struct pci_device_id *pci_id) 1433 + static int __devinit 1434 + snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) 1733 1435 { 1734 1436 static int dev; 1735 1437 snd_card_t *card; ··· 1765 1443 strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); 1766 1444 1767 1445 if ((err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip)) < 0) { 1768 - snd_card_free(card); 1769 - return err; 1446 + goto out_err; 1770 1447 } 1771 1448 1772 1449 if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, 1773 1450 chip->mpu_port, 1, pci->irq, 0, 1774 1451 &chip->rmidi)) < 0) { 1775 1452 snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); 1776 - snd_card_free(card); 1777 - return err; 1453 + goto out_err; 1454 + } 1455 + 1456 + if ((err = snd_azf3328_timer(chip, 0)) < 0) { 1457 + goto out_err; 1778 1458 } 1779 1459 1780 1460 if ((err = snd_azf3328_pcm(chip, 0)) < 0) { 1781 - snd_card_free(card); 1782 - return err; 1461 + goto out_err; 1783 1462 } 1784 1463 1785 1464 if (snd_opl3_create(card, chip->synth_port, chip->synth_port+2, ··· 1789 1466 chip->synth_port, chip->synth_port+2 ); 1790 1467 } else { 1791 1468 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { 1792 - snd_card_free(card); 1793 - return err; 1469 + goto out_err; 1794 1470 } 1795 1471 } 1796 - 1797 - snd_azf3328_dbgio(chip, "create"); 1798 1472 1799 1473 sprintf(card->longname, "%s at 0x%lx, irq %i", 1800 1474 card->shortname, chip->codec_port, chip->irq); 1801 1475 1802 1476 if ((err = snd_card_register(card)) < 0) { 1803 - snd_card_free(card); 1804 - return err; 1477 + goto out_err; 1805 1478 } 1806 1479 1807 1480 #ifdef MODULE 1808 1481 printk( 1809 - "azt3328: Experimental driver for Aztech AZF3328-based soundcards such as PCI168.\n" 1810 - "azt3328: ZERO support from Aztech: you might think hard about future purchase.\n" 1811 - "azt3328: Feel free to contact hw7oshyuv3001@sneakemail.com for bug reports etc.!\n"); 1482 + "azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168\n" 1483 + "azt3328: (hardware was completely undocumented - ZERO support from Aztech).\n" 1484 + "azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n" 1485 + "azt3328: User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n", 1486 + 1024000 / seqtimer_scaling, seqtimer_scaling); 1812 1487 #endif 1813 1488 1814 1489 if (snd_azf3328_config_joystick(chip, dev) < 0) 1815 - snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, 1816 - snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); 1490 + snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR, 1491 + snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); 1817 1492 1818 1493 pci_set_drvdata(pci, card); 1819 1494 dev++; 1820 1495 1496 + err = 0; 1497 + goto out; 1498 + 1499 + out_err: 1500 + snd_card_free(card); 1501 + 1502 + out: 1821 1503 snd_azf3328_dbgcallleave(); 1822 - return 0; 1504 + return err; 1823 1505 } 1824 1506 1825 - static void __devexit snd_azf3328_remove(struct pci_dev *pci) 1507 + static void __devexit 1508 + snd_azf3328_remove(struct pci_dev *pci) 1826 1509 { 1827 1510 snd_azf3328_dbgcallenter(); 1828 1511 snd_card_free(pci_get_drvdata(pci)); ··· 1844 1515 .remove = __devexit_p(snd_azf3328_remove), 1845 1516 }; 1846 1517 1847 - static int __init alsa_card_azf3328_init(void) 1518 + static int __init 1519 + alsa_card_azf3328_init(void) 1848 1520 { 1849 1521 int err; 1850 1522 snd_azf3328_dbgcallenter(); ··· 1854 1524 return err; 1855 1525 } 1856 1526 1857 - static void __exit alsa_card_azf3328_exit(void) 1527 + static void __exit 1528 + alsa_card_azf3328_exit(void) 1858 1529 { 1859 1530 snd_azf3328_dbgcallenter(); 1860 1531 pci_unregister_driver(&driver);
+72 -63
sound/pci/azt3328.h
··· 1 - #ifndef __SOUND_AZF3328_H 2 - #define __SOUND_AZF3328_H 1 + #ifndef __SOUND_AZT3328_H 2 + #define __SOUND_AZT3328_H 3 3 4 - /* type argument to use for the I/O functions */ 5 - #define WORD_VALUE 0x1000 6 - #define DWORD_VALUE 0x2000 7 - #define BYTE_VALUE 0x4000 4 + /* "PU" == "power-up value", as tested on PCI168 PCI rev. 10 */ 8 5 9 6 /*** main I/O area port indices ***/ 10 7 /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ 11 - /* the driver initialisation suggests a layout of 3 main areas: 12 - * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe DirectX 13 - * timer ???). and probably another area from 0x60 to 0x6f 14 - * (IRQ management, power management etc. ???). */ 15 - /* playback area */ 16 - #define IDX_IO_PLAY_FLAGS 0x00 8 + /* the driver initialisation suggests a layout of 4 main areas: 9 + * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). 10 + * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, 11 + * power management etc.???). */ 12 + 13 + /** playback area **/ 14 + #define IDX_IO_PLAY_FLAGS 0x00 /* PU:0x0000 */ 17 15 /* able to reactivate output after output muting due to 8/16bit 18 16 * output change, just like 0x0002. 19 17 * 0x0001 is the only bit that's able to start the DMA counter */ ··· 27 29 #define DMA_EPILOGUE_SOMETHING 0x0010 28 30 #define DMA_SOMETHING_ELSE 0x0020 /* ??? */ 29 31 #define SOMETHING_UNMODIFIABLE 0xffc0 /* unused ? not modifiable */ 30 - #define IDX_IO_PLAY_IRQMASK 0x02 32 + #define IDX_IO_PLAY_IRQTYPE 0x02 /* PU:0x0001 */ 31 33 /* write back to flags in case flags are set, in order to ACK IRQ in handler 32 34 * (bit 1 of port 0x64 indicates interrupt for one of these three types) 33 35 * sometimes in this case it just writes 0xffff to globally ACK all IRQs ··· 39 41 #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ 40 42 #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ 41 43 #define IRQMASK_UNMODIFIABLE 0xffe0 /* unused ? not modifiable */ 42 - #define IDX_IO_PLAY_DMA_START_1 0x04 /* start address of 1st DMA play area */ 43 - #define IDX_IO_PLAY_DMA_START_2 0x08 /* start address of 2nd DMA play area */ 44 - #define IDX_IO_PLAY_DMA_LEN_1 0x0c /* length of 1st DMA play area */ 45 - #define IDX_IO_PLAY_DMA_LEN_2 0x0e /* length of 2nd DMA play area */ 46 - #define IDX_IO_PLAY_DMA_CURRPOS 0x10 /* current DMA position */ 47 - #define IDX_IO_PLAY_DMA_CURROFS 0x14 /* offset within current DMA play area */ 48 - #define IDX_IO_PLAY_SOUNDFORMAT 0x16 44 + #define IDX_IO_PLAY_DMA_START_1 0x04 /* start address of 1st DMA play area, PU:0x00000000 */ 45 + #define IDX_IO_PLAY_DMA_START_2 0x08 /* start address of 2nd DMA play area, PU:0x00000000 */ 46 + #define IDX_IO_PLAY_DMA_LEN_1 0x0c /* length of 1st DMA play area, PU:0x0000 */ 47 + #define IDX_IO_PLAY_DMA_LEN_2 0x0e /* length of 2nd DMA play area, PU:0x0000 */ 48 + #define IDX_IO_PLAY_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */ 49 + #define IDX_IO_PLAY_DMA_CURROFS 0x14 /* offset within current DMA play area, PU:0x0000 */ 50 + #define IDX_IO_PLAY_SOUNDFORMAT 0x16 /* PU:0x0010 */ 49 51 /* all unspecified bits can't be modified */ 50 52 #define SOUNDFORMAT_FREQUENCY_MASK 0x000f 53 + #define SOUNDFORMAT_XTAL1 0x00 54 + #define SOUNDFORMAT_XTAL2 0x01 51 55 /* all _SUSPECTED_ values are not used by Windows drivers, so we don't 52 56 * have any hard facts, only rough measurements */ 53 - #define SOUNDFORMAT_FREQ_SUSPECTED_4000 0x0c 54 - #define SOUNDFORMAT_FREQ_SUSPECTED_4800 0x0a 55 - #define SOUNDFORMAT_FREQ_5510 0x0d 56 - #define SOUNDFORMAT_FREQ_6620 0x0b 57 - #define SOUNDFORMAT_FREQ_8000 0x00 /* also 0x0e ? */ 58 - #define SOUNDFORMAT_FREQ_9600 0x08 59 - #define SOUNDFORMAT_FREQ_SUSPECTED_12000 0x09 60 - #define SOUNDFORMAT_FREQ_11025 0x01 /* also 0x0f ? */ 61 - #define SOUNDFORMAT_FREQ_16000 0x02 62 - #define SOUNDFORMAT_FREQ_22050 0x03 63 - #define SOUNDFORMAT_FREQ_32000 0x04 64 - #define SOUNDFORMAT_FREQ_44100 0x05 65 - #define SOUNDFORMAT_FREQ_48000 0x06 66 - #define SOUNDFORMAT_FREQ_SUSPECTED_64000 0x07 57 + #define SOUNDFORMAT_FREQ_SUSPECTED_4000 0x0c | SOUNDFORMAT_XTAL1 58 + #define SOUNDFORMAT_FREQ_SUSPECTED_4800 0x0a | SOUNDFORMAT_XTAL1 59 + #define SOUNDFORMAT_FREQ_5510 0x0c | SOUNDFORMAT_XTAL2 60 + #define SOUNDFORMAT_FREQ_6620 0x0a | SOUNDFORMAT_XTAL2 61 + #define SOUNDFORMAT_FREQ_8000 0x00 | SOUNDFORMAT_XTAL1 /* also 0x0e | SOUNDFORMAT_XTAL1? */ 62 + #define SOUNDFORMAT_FREQ_9600 0x08 | SOUNDFORMAT_XTAL1 63 + #define SOUNDFORMAT_FREQ_11025 0x00 | SOUNDFORMAT_XTAL2 /* also 0x0e | SOUNDFORMAT_XTAL2? */ 64 + #define SOUNDFORMAT_FREQ_SUSPECTED_13240 0x08 | SOUNDFORMAT_XTAL2 /* seems to be 6620 *2 */ 65 + #define SOUNDFORMAT_FREQ_16000 0x02 | SOUNDFORMAT_XTAL1 66 + #define SOUNDFORMAT_FREQ_22050 0x02 | SOUNDFORMAT_XTAL2 67 + #define SOUNDFORMAT_FREQ_32000 0x04 | SOUNDFORMAT_XTAL1 68 + #define SOUNDFORMAT_FREQ_44100 0x04 | SOUNDFORMAT_XTAL2 69 + #define SOUNDFORMAT_FREQ_48000 0x06 | SOUNDFORMAT_XTAL1 70 + #define SOUNDFORMAT_FREQ_SUSPECTED_66200 0x06 | SOUNDFORMAT_XTAL2 /* 66200 (13240 * 5); 64000 may have been nicer :-\ */ 67 71 #define SOUNDFORMAT_FLAG_16BIT 0x0010 68 72 #define SOUNDFORMAT_FLAG_2CHANNELS 0x0020 69 - /* recording area (see also: playback bit flag definitions) */ 70 - #define IDX_IO_REC_FLAGS 0x20 /* ?? */ 71 - #define IDX_IO_REC_IRQMASK 0x22 /* ?? */ 73 + 74 + /** recording area (see also: playback bit flag definitions) **/ 75 + #define IDX_IO_REC_FLAGS 0x20 /* ??, PU:0x0000 */ 76 + #define IDX_IO_REC_IRQTYPE 0x22 /* ??, PU:0x0000 */ 72 77 #define IRQ_REC_SOMETHING 0x0001 /* something & ACK */ 73 78 #define IRQ_FINISHED_RECBUF_1 0x0002 /* 1st dmabuf finished & ACK */ 74 79 #define IRQ_FINISHED_RECBUF_2 0x0004 /* 2nd dmabuf finished & ACK */ ··· 79 78 * but OTOH they are most likely at port 0x22 instead */ 80 79 #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ 81 80 #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ 82 - #define IDX_IO_REC_DMA_START_1 0x24 83 - #define IDX_IO_REC_DMA_START_2 0x28 84 - #define IDX_IO_REC_DMA_LEN_1 0x2c 85 - #define IDX_IO_REC_DMA_LEN_2 0x2e 86 - #define IDX_IO_REC_DMA_CURRPOS 0x30 87 - #define IDX_IO_REC_DMA_CURROFS 0x34 88 - #define IDX_IO_REC_SOUNDFORMAT 0x36 89 - /* some third area ? (after playback and recording) */ 90 - #define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init */ 81 + #define IDX_IO_REC_DMA_START_1 0x24 /* PU:0x00000000 */ 82 + #define IDX_IO_REC_DMA_START_2 0x28 /* PU:0x00000000 */ 83 + #define IDX_IO_REC_DMA_LEN_1 0x2c /* PU:0x0000 */ 84 + #define IDX_IO_REC_DMA_LEN_2 0x2e /* PU:0x0000 */ 85 + #define IDX_IO_REC_DMA_CURRPOS 0x30 /* PU:0x00000000 */ 86 + #define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ 87 + #define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ 88 + 89 + /** hmm, what is this I/O area for? MPU401?? (after playback, recording, ???, timer) **/ 90 + #define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ 91 91 /* general */ 92 - #define IDX_IO_60H 0x60 /* writing 0xffff returns 0xffff */ 93 - #define IDX_IO_62H 0x62 /* writing to WORD 0x0062 can hang the box ! --> responsible for IRQ management as a whole ?? */ 94 - #define IDX_IO_IRQ63H 0x63 /* FIXME !! */ 95 - #define IO_IRQ63H_SOMETHING 0x04 /* being set in IRQ handler in case port 0x00 had 0x0020 set upon IRQ handler */ 92 + #define IDX_IO_42H 0x42 /* PU:0x0001 */ 93 + 94 + /** DirectX timer, main interrupt area (FIXME: and something else?) **/ 95 + #define IDX_IO_TIMER_VALUE 0x60 /* found this timer area by pure luck :-) */ 96 + #define TIMER_VALUE_MASK 0x000fffffUL /* timer countdown value; triggers IRQ when timer is finished */ 97 + #define TIMER_ENABLE_COUNTDOWN 0x01000000UL /* activate the timer countdown */ 98 + #define TIMER_ENABLE_IRQ 0x02000000UL /* trigger timer IRQ on zero transition */ 99 + #define TIMER_ACK_IRQ 0x04000000UL /* being set in IRQ handler in case port 0x00 (hmm, not port 0x64!?!?) had 0x0020 set upon IRQ handler */ 96 100 #define IDX_IO_IRQSTATUS 0x64 97 101 #define IRQ_PLAYBACK 0x0001 98 102 #define IRQ_RECORDING 0x0002 99 103 #define IRQ_MPU401 0x0010 100 - #define IRQ_SOMEIRQ 0x0020 /* ???? */ 101 - #define IRQ_WHO_KNOWS_UNUSED 0x00e0 /* probably unused */ 104 + #define IRQ_TIMER 0x0020 /* DirectX timer */ 105 + #define IRQ_UNKNOWN1 0x0040 /* probably unused */ 106 + #define IRQ_UNKNOWN2 0x0080 /* probably unused */ 102 107 #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ 103 - #define IDX_IO_SOME_VALUE 0x68 /* this is always set to 0x3ff, and writable; maybe some buffer limit, but I couldn't find out more */ 104 - #define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback !!! maybe power management ?? */ 105 - #define IDX_IO_6CH 0x6C /* this WORD can have all its bits activated ? */ 108 + #define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */ 109 + #define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback!!! maybe power management?? */ 110 + #define IDX_IO_6CH 0x6C 106 111 #define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */ 107 112 /* further I/O indices not saved/restored, so probably not used */ 113 + 108 114 109 115 /*** I/O 2 area port indices ***/ 110 116 /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ 111 117 #define IDX_IO2_LEGACY_ADDR 0x04 112 - #define LEGACY_SOMETHING 0x01 /* OPL3 ?? */ 118 + #define LEGACY_SOMETHING 0x01 /* OPL3?? */ 113 119 #define LEGACY_JOY 0x08 120 + 114 121 115 122 /*** mixer I/O area port indices ***/ 116 123 /* (only 0x22 of 0x40 bytes saved/restored by Windows driver) ··· 157 148 /* unlisted bits are unmodifiable */ 158 149 #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e 159 150 #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 160 - #define IDX_MIXER_ADVCTL2 0x20 /* resembles AC97_GENERAL_PURPOSE reg ! */ 151 + #define IDX_MIXER_ADVCTL2 0x20 /* resembles AC97_GENERAL_PURPOSE reg! */ 161 152 /* unlisted bits are unmodifiable */ 162 - #define MIXER_ADVCTL2_BIT7 0x0080 /* WaveOut 3D Bypass ? mutes WaveOut at LineOut */ 163 - #define MIXER_ADVCTL2_BIT8 0x0100 /* is this Modem Out Select ? */ 164 - #define MIXER_ADVCTL2_BIT9 0x0200 /* Mono Select Source ? */ 165 - #define MIXER_ADVCTL2_BIT13 0x2000 /* 3D enable ? */ 153 + #define MIXER_ADVCTL2_BIT7 0x0080 /* WaveOut 3D Bypass? mutes WaveOut at LineOut */ 154 + #define MIXER_ADVCTL2_BIT8 0x0100 /* is this Modem Out Select? */ 155 + #define MIXER_ADVCTL2_BIT9 0x0200 /* Mono Select Source? */ 156 + #define MIXER_ADVCTL2_BIT13 0x2000 /* 3D enable? */ 166 157 #define MIXER_ADVCTL2_BIT15 0x8000 /* unknown */ 167 158 168 - #define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown ??? */ 159 + #define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */ 169 160 170 161 /* driver internal flags */ 171 162 #define SET_CHAN_LEFT 1 172 163 #define SET_CHAN_RIGHT 2 173 164 174 - #endif /* __SOUND_AZF3328_H */ 165 + #endif /* __SOUND_AZT3328_H */