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