ALSA: azt3328: large codec cleanup, add I2S port etc.
[deliverable/linux.git] / sound / pci / azt3328.c
CommitLineData
1da177e4
LT
1/*
2 * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
dfbf9511 3 * Copyright (C) 2002, 2005 - 2009 by Andreas Mohr <andi AT lisas.de>
1da177e4
LT
4 *
5 * Framework borrowed from Bart Hartgers's als4000.c.
6 * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),
7 * found in a Fujitsu-Siemens PC ("Cordant", aluminum case).
8 * Other versions are:
9 * PCI168 A(W), sub ID 1800
10 * PCI168 A/AP, sub ID 8000
11 * Please give me feedback in case you try my driver with one of these!!
12 *
dfbf9511
AM
13 * Keywords: Windows XP Vista 168nt4-125.zip 168win95-125.zip PCI 168 download
14 * (XP/Vista do not support this card at all but every Linux distribution
15 * has very good support out of the box;
16 * just to make sure that the right people hit this and get to know that,
17 * despite the high level of Internet ignorance - as usual :-P -
18 * about Linux support for this card)
19 *
1da177e4
LT
20 * GPL LICENSE
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 *
35 * NOTES
36 * Since Aztech does not provide any chipset documentation,
37 * even on repeated request to various addresses,
38 * and the answer that was finally given was negative
39 * (and I was stupid enough to manage to get hold of a PCI168 soundcard
40 * in the first place >:-P}),
41 * I was forced to base this driver on reverse engineering
42 * (3 weeks' worth of evenings filled with driver work).
e2f87260 43 * (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros)
1da177e4 44 *
02330fba
AM
45 * It is quite likely that the AZF3328 chip is the PCI cousin of the
46 * AZF3318 ("azt1020 pnp", "MM Pro 16") ISA chip, given very similar specs.
47 *
1da177e4 48 * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name
02330fba
AM
49 * for compatibility reasons) from Azfin (joint-venture of Aztech and Fincitec,
50 * Fincitec acquired by National Semiconductor in 2002, together with the
51 * Fincitec-related company ARSmikro) has the following features:
1da177e4 52 *
02330fba
AM
53 * - compatibility & compliance:
54 * - Microsoft PC 97 ("PC 97 Hardware Design Guide",
55 * http://www.microsoft.com/whdc/archive/pcguides.mspx)
56 * - Microsoft PC 98 Baseline Audio
57 * - MPU401 UART
58 * - Sound Blaster Emulation (DOS Box)
1da177e4 59 * - builtin AC97 conformant codec (SNR over 80dB)
13769e3f
AM
60 * Note that "conformant" != "compliant"!! this chip's mixer register layout
61 * *differs* from the standard AC97 layout:
62 * they chose to not implement the headphone register (which is not a
63 * problem since it's merely optional), yet when doing this, they committed
64 * the grave sin of letting other registers follow immediately instead of
65 * keeping a headphone dummy register, thereby shifting the mixer register
66 * addresses illegally. So far unfortunately it looks like the very flexible
67 * ALSA AC97 support is still not enough to easily compensate for such a
68 * grave layout violation despite all tweaks and quirks mechanisms it offers.
02330fba 69 * - builtin genuine OPL3 - verified to work fine, 20080506
1da177e4 70 * - full duplex 16bit playback/record at independent sampling rate
02330fba
AM
71 * - MPU401 (+ legacy address support, claimed by one official spec sheet)
72 * FIXME: how to enable legacy addr??
1da177e4 73 * - game port (legacy address support)
e24a121a 74 * - builtin DirectInput support, helps reduce CPU overhead (interrupt-driven
02330fba
AM
75 * features supported). - See common term "Digital Enhanced Game Port"...
76 * (probably DirectInput 3.0 spec - confirm)
77 * - builtin 3D enhancement (said to be YAMAHA Ymersion)
1da177e4 78 * - built-in General DirectX timer having a 20 bits counter
d91c64c8 79 * with 1us resolution (see below!)
02330fba 80 * - I2S serial output port for external DAC
dfbf9511 81 * [FIXME: 3.3V or 5V level? maximum rate is 66.2kHz right?]
1da177e4
LT
82 * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI
83 * - supports hardware volume control
84 * - single chip low cost solution (128 pin QFP)
dfbf9511 85 * - supports programmable Sub-vendor and Sub-system ID [24C02 SEEPROM chip]
1da177e4 86 * required for Microsoft's logo compliance (FIXME: where?)
02330fba
AM
87 * At least the Trident 4D Wave DX has one bit somewhere
88 * to enable writes to PCI subsystem VID registers, that should be it.
89 * This might easily be in extended PCI reg space, since PCI168 also has
90 * some custom data starting at 0x80. What kind of config settings
91 * are located in our extended PCI space anyway??
1da177e4 92 * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms
dfbf9511 93 * [TDA1517P chip]
1da177e4 94 *
d91c64c8
AM
95 * Note that this driver now is actually *better* than the Windows driver,
96 * since it additionally supports the card's 1MHz DirectX timer - just try
97 * the following snd-seq module parameters etc.:
98 * - options snd-seq seq_default_timer_class=2 seq_default_timer_sclass=0
99 * seq_default_timer_card=0 seq_client_load=1 seq_default_timer_device=0
100 * seq_default_timer_subdevice=0 seq_default_timer_resolution=1000000
101 * - "timidity -iAv -B2,8 -Os -EFreverb=0"
102 * - "pmidi -p 128:0 jazz.mid"
103 *
02330fba
AM
104 * OPL3 hardware playback testing, try something like:
105 * cat /proc/asound/hwdep
106 * and
107 * aconnect -o
108 * Then use
109 * sbiload -Dhw:x,y --opl3 /usr/share/sounds/opl3/std.o3 ......./drums.o3
110 * where x,y is the xx-yy number as given in hwdep.
111 * Then try
112 * pmidi -p a:b jazz.mid
113 * where a:b is the client number plus 0 usually, as given by aconnect above.
114 * Oh, and make sure to unmute the FM mixer control (doh!)
115 * NOTE: power use during OPL3 playback is _VERY_ high (70W --> 90W!)
116 * despite no CPU activity, possibly due to hindering ACPI idling somehow.
117 * Shouldn't be a problem of the AZF3328 chip itself, I'd hope.
118 * Higher PCM / FM mixer levels seem to conflict (causes crackling),
119 * at least sometimes. Maybe even use with hardware sequencer timer above :)
120 * adplay/adplug-utils might soon offer hardware-based OPL3 playback, too.
121 *
1da177e4
LT
122 * Certain PCI versions of this card are susceptible to DMA traffic underruns
123 * in some systems (resulting in sound crackling/clicking/popping),
124 * probably because they don't have a DMA FIFO buffer or so.
125 * Overview (PCI ID/PCI subID/PCI rev.):
126 * - no DMA crackling on SiS735: 0x50DC/0x1801/16
127 * - unknown performance: 0x50DC/0x1801/10
d91c64c8
AM
128 * (well, it's not bad on an Athlon 1800 with now very optimized IRQ handler)
129 *
1da177e4
LT
130 * Crackling happens with VIA chipsets or, in my case, an SiS735, which is
131 * supposed to be very fast and supposed to get rid of crackling much
132 * better than a VIA, yet ironically I still get crackling, like many other
133 * people with the same chipset.
134 * Possible remedies:
02330fba
AM
135 * - use speaker (amplifier) output instead of headphone output
136 * (in case crackling is due to overloaded output clipping)
1da177e4
LT
137 * - plug card into a different PCI slot, preferrably one that isn't shared
138 * too much (this helps a lot, but not completely!)
139 * - get rid of PCI VGA card, use AGP instead
140 * - upgrade or downgrade BIOS
141 * - fiddle with PCI latency settings (setpci -v -s BUSID latency_timer=XX)
142 * Not too helpful.
143 * - Disable ACPI/power management/"Auto Detect RAM/PCI Clk" in BIOS
02330fba 144 *
1da177e4 145 * BUGS
02330fba 146 * - full-duplex might *still* be problematic, however a recent test was fine
e24a121a
AM
147 * - (non-bug) "Bass/Treble or 3D settings don't work" - they do get evaluated
148 * if you set PCM output switch to "pre 3D" instead of "post 3D".
149 * If this can't be set, then get a mixer application that Isn't Stupid (tm)
150 * (e.g. kmix, gamix) - unfortunately several are!!
02330fba
AM
151 * - locking is not entirely clean, especially the audio stream activity
152 * ints --> may be racy
153 * - an _unconnected_ secondary joystick at the gameport will be reported
154 * to be "active" (floating values, not precisely -1) due to the way we need
155 * to read the Digital Enhanced Game Port. Not sure whether it is fixable.
156 *
1da177e4 157 * TODO
dfbf9511
AM
158 * - use PCI_VDEVICE
159 * - verify driver status on x86_64
160 * - test multi-card driver operation
161 * - (ab)use 1MHz DirectX timer as kernel clocksource
1da177e4 162 * - test MPU401 MIDI playback etc.
02330fba 163 * - add more power micro-management (disable various units of the card
dfbf9511
AM
164 * as long as they're unused, to improve audio quality and save power).
165 * However this requires more I/O ports which I haven't figured out yet
166 * and which thus might not even exist...
ca54bde3
AM
167 * The standard suspend/resume functionality could probably make use of
168 * some improvement, too...
1da177e4 169 * - figure out what all unknown port bits are responsible for
13769e3f
AM
170 * - figure out some cleverly evil scheme to possibly make ALSA AC97 code
171 * fully accept our quite incompatible ""AC97"" mixer and thus save some
172 * code (but I'm not too optimistic that doing this is possible at all)
02330fba 173 * - use MMIO (memory-mapped I/O)? Slightly faster access, e.g. for gameport.
1da177e4
LT
174 */
175
1da177e4
LT
176#include <asm/io.h>
177#include <linux/init.h>
178#include <linux/pci.h>
179#include <linux/delay.h>
180#include <linux/slab.h>
181#include <linux/gameport.h>
182#include <linux/moduleparam.h>
910638ae 183#include <linux/dma-mapping.h>
1da177e4
LT
184#include <sound/core.h>
185#include <sound/control.h>
186#include <sound/pcm.h>
187#include <sound/rawmidi.h>
188#include <sound/mpu401.h>
189#include <sound/opl3.h>
190#include <sound/initval.h>
191#include "azt3328.h"
192
d91c64c8 193MODULE_AUTHOR("Andreas Mohr <andi AT lisas.de>");
1da177e4
LT
194MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)");
195MODULE_LICENSE("GPL");
196MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
197
198#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
02330fba 199#define SUPPORT_GAMEPORT 1
1da177e4
LT
200#endif
201
dfbf9511
AM
202/* === Debug settings ===
203 Further diagnostic functionality than the settings below
204 does not need to be provided, since one can easily write a bash script
205 to dump the card's I/O ports (those listed in lspci -v -v):
206 function dump()
207 {
208 local descr=$1; local addr=$2; local count=$3
209
210 echo "${descr}: ${count} @ ${addr}:"
211 dd if=/dev/port skip=$[${addr}] count=${count} bs=1 2>/dev/null| hexdump -C
212 }
213 and then use something like
214 "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8",
215 "dump codec00 0xa800 32", "dump mixer 0xb800 64", "dump synth 0xbc00 8",
216 possibly within a "while true; do ... sleep 1; done" loop.
217 Tweaking ports could be done using
218 VALSTRING="`printf "%02x" $value`"
219 printf "\x""$VALSTRING"|dd of=/dev/port seek=$[${addr}] bs=1 2>/dev/null
220*/
221
1da177e4
LT
222#define DEBUG_MISC 0
223#define DEBUG_CALLS 0
224#define DEBUG_MIXER 0
225#define DEBUG_PLAY_REC 0
226#define DEBUG_IO 0
d91c64c8 227#define DEBUG_TIMER 0
02330fba 228#define DEBUG_GAME 0
1da177e4
LT
229#define MIXER_TESTING 0
230
231#if DEBUG_MISC
232#define snd_azf3328_dbgmisc(format, args...) printk(KERN_ERR format, ##args)
233#else
234#define snd_azf3328_dbgmisc(format, args...)
02330fba 235#endif
1da177e4
LT
236
237#if DEBUG_CALLS
238#define snd_azf3328_dbgcalls(format, args...) printk(format, ##args)
9bf8e7dd
HH
239#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
240#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
1da177e4
LT
241#else
242#define snd_azf3328_dbgcalls(format, args...)
243#define snd_azf3328_dbgcallenter()
244#define snd_azf3328_dbgcallleave()
02330fba 245#endif
1da177e4
LT
246
247#if DEBUG_MIXER
ee419653 248#define snd_azf3328_dbgmixer(format, args...) printk(KERN_DEBUG format, ##args)
1da177e4
LT
249#else
250#define snd_azf3328_dbgmixer(format, args...)
02330fba 251#endif
1da177e4
LT
252
253#if DEBUG_PLAY_REC
ee419653 254#define snd_azf3328_dbgplay(format, args...) printk(KERN_DEBUG format, ##args)
1da177e4
LT
255#else
256#define snd_azf3328_dbgplay(format, args...)
02330fba 257#endif
1da177e4 258
d91c64c8 259#if DEBUG_MISC
ee419653 260#define snd_azf3328_dbgtimer(format, args...) printk(KERN_DEBUG format, ##args)
1da177e4 261#else
d91c64c8 262#define snd_azf3328_dbgtimer(format, args...)
02330fba
AM
263#endif
264
265#if DEBUG_GAME
ee419653 266#define snd_azf3328_dbggame(format, args...) printk(KERN_DEBUG format, ##args)
02330fba
AM
267#else
268#define snd_azf3328_dbggame(format, args...)
269#endif
d91c64c8 270
1da177e4
LT
271static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
272module_param_array(index, int, NULL, 0444);
273MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard.");
274
275static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
276module_param_array(id, charp, NULL, 0444);
277MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard.");
278
279static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
280module_param_array(enable, bool, NULL, 0444);
281MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
282
d91c64c8
AM
283static int seqtimer_scaling = 128;
284module_param(seqtimer_scaling, int, 0444);
285MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");
1da177e4 286
dfbf9511
AM
287struct snd_azf3328_codec_data {
288 unsigned long io_base;
02330fba 289 struct snd_pcm_substream *substream;
dfbf9511
AM
290 bool running;
291 const char *name;
02330fba
AM
292};
293
dfbf9511
AM
294enum snd_azf3328_codec_type {
295 AZF_CODEC_PLAYBACK = 0,
296 AZF_CODEC_CAPTURE = 1,
297 AZF_CODEC_I2S_OUT = 2,
02330fba
AM
298};
299
95de7766 300struct snd_azf3328 {
d91c64c8 301 /* often-used fields towards beginning, then grouped */
02330fba 302
dfbf9511 303 unsigned long ctrl_io; /* usually 0xb000, size 128 */
02330fba
AM
304 unsigned long game_io; /* usually 0xb400, size 8 */
305 unsigned long mpu_io; /* usually 0xb800, size 4 */
306 unsigned long opl3_io; /* usually 0xbc00, size 8 */
307 unsigned long mixer_io; /* usually 0xc000, size 64 */
1da177e4 308
d91c64c8 309 spinlock_t reg_lock;
1da177e4 310
95de7766 311 struct snd_timer *timer;
02330fba 312
dfbf9511
AM
313 struct snd_pcm *pcm[3];
314
315 /* playback, recording and I2S out codecs */
316 struct snd_azf3328_codec_data codecs[3];
1da177e4 317
95de7766
TI
318 struct snd_card *card;
319 struct snd_rawmidi *rmidi;
d91c64c8 320
02330fba 321#ifdef SUPPORT_GAMEPORT
d91c64c8 322 struct gameport *gameport;
dfbf9511 323 u16 axes[4];
d91c64c8 324#endif
1da177e4 325
d91c64c8
AM
326 struct pci_dev *pci;
327 int irq;
ca54bde3 328
627d3e7a
AM
329 /* register 0x6a is write-only, thus need to remember setting.
330 * If we need to add more registers here, then we might try to fold this
331 * into some transparent combined shadow register handling with
332 * CONFIG_PM register storage below, but that's slightly difficult. */
dfbf9511 333 u16 shadow_reg_ctrl_6AH;
627d3e7a 334
ca54bde3
AM
335#ifdef CONFIG_PM
336 /* register value containers for power management
337 * Note: not always full I/O range preserved (just like Win driver!) */
dfbf9511 338 u16 saved_regs_ctrl[AZF_IO_SIZE_CTRL_PM / 2];
02330fba
AM
339 u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2];
340 u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2];
341 u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2];
ca54bde3
AM
342 u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2];
343#endif
95de7766 344};
d91c64c8 345
f40b6890 346static const struct pci_device_id snd_azf3328_ids[] = {
1da177e4
LT
347 { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */
348 { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */
349 { 0, }
350};
351
352MODULE_DEVICE_TABLE(pci, snd_azf3328_ids);
353
02330fba
AM
354
355static int
dfbf9511 356snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set)
02330fba
AM
357{
358 u8 prev = inb(reg), new;
359
360 new = (do_set) ? (prev|mask) : (prev & ~mask);
361 /* we need to always write the new value no matter whether it differs
362 * or not, since some register bits don't indicate their setting */
363 outb(new, reg);
364 if (new != prev)
365 return 1;
366
367 return 0;
368}
369
d91c64c8 370static inline void
dfbf9511
AM
371snd_azf3328_codec_outb(const struct snd_azf3328_codec_data *codec,
372 unsigned reg,
373 u8 value
374)
d91c64c8 375{
dfbf9511 376 outb(value, codec->io_base + reg);
d91c64c8
AM
377}
378
379static inline u8
dfbf9511 380snd_azf3328_codec_inb(const struct snd_azf3328_codec_data *codec, unsigned reg)
d91c64c8 381{
dfbf9511 382 return inb(codec->io_base + reg);
d91c64c8
AM
383}
384
385static inline void
dfbf9511
AM
386snd_azf3328_codec_outw(const struct snd_azf3328_codec_data *codec,
387 unsigned reg,
388 u16 value
389)
d91c64c8 390{
dfbf9511 391 outw(value, codec->io_base + reg);
d91c64c8
AM
392}
393
394static inline u16
dfbf9511 395snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg)
02330fba 396{
dfbf9511 397 return inw(codec->io_base + reg);
02330fba
AM
398}
399
400static inline void
dfbf9511
AM
401snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec,
402 unsigned reg,
403 u32 value
404)
02330fba 405{
dfbf9511 406 outl(value, codec->io_base + reg);
02330fba
AM
407}
408
409static inline u32
dfbf9511
AM
410snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg)
411{
412 return inl(codec->io_base + reg);
413}
414
415static inline void
416snd_azf3328_ctrl_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
d91c64c8 417{
dfbf9511
AM
418 outb(value, chip->ctrl_io + reg);
419}
420
421static inline u8
422snd_azf3328_ctrl_inb(const struct snd_azf3328 *chip, unsigned reg)
423{
424 return inb(chip->ctrl_io + reg);
425}
426
427static inline void
428snd_azf3328_ctrl_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
429{
430 outw(value, chip->ctrl_io + reg);
431}
432
433static inline void
434snd_azf3328_ctrl_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value)
435{
436 outl(value, chip->ctrl_io + reg);
d91c64c8
AM
437}
438
439static inline void
02330fba 440snd_azf3328_game_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
d91c64c8 441{
02330fba 442 outb(value, chip->game_io + reg);
d91c64c8
AM
443}
444
445static inline void
02330fba 446snd_azf3328_game_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
1da177e4 447{
02330fba 448 outw(value, chip->game_io + reg);
1da177e4
LT
449}
450
d91c64c8 451static inline u8
02330fba
AM
452snd_azf3328_game_inb(const struct snd_azf3328 *chip, unsigned reg)
453{
454 return inb(chip->game_io + reg);
455}
456
457static inline u16
458snd_azf3328_game_inw(const struct snd_azf3328 *chip, unsigned reg)
1da177e4 459{
02330fba 460 return inw(chip->game_io + reg);
1da177e4
LT
461}
462
d91c64c8 463static inline void
02330fba 464snd_azf3328_mixer_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
1da177e4 465{
02330fba 466 outw(value, chip->mixer_io + reg);
d91c64c8
AM
467}
468
469static inline u16
02330fba 470snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg)
d91c64c8 471{
02330fba 472 return inw(chip->mixer_io + reg);
1da177e4
LT
473}
474
02330fba
AM
475#define AZF_MUTE_BIT 0x80
476
dfbf9511 477static bool
02330fba 478snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
dfbf9511 479 unsigned reg, bool do_mute
02330fba 480)
1da177e4 481{
02330fba 482 unsigned long portbase = chip->mixer_io + reg + 1;
dfbf9511 483 bool updated;
1da177e4
LT
484
485 /* the mute bit is on the *second* (i.e. right) register of a
486 * left/right channel setting */
02330fba
AM
487 updated = snd_azf3328_io_reg_setb(portbase, AZF_MUTE_BIT, do_mute);
488
489 /* indicate whether it was muted before */
490 return (do_mute) ? !updated : updated;
1da177e4
LT
491}
492
d91c64c8 493static void
02330fba
AM
494snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip,
495 unsigned reg,
496 unsigned char dst_vol_left,
497 unsigned char dst_vol_right,
498 int chan_sel, int delay
499)
1da177e4 500{
02330fba 501 unsigned long portbase = chip->mixer_io + reg;
1da177e4 502 unsigned char curr_vol_left = 0, curr_vol_right = 0;
02330fba
AM
503 int left_change = 0, right_change = 0;
504
1da177e4 505 snd_azf3328_dbgcallenter();
02330fba
AM
506
507 if (chan_sel & SET_CHAN_LEFT) {
d91c64c8 508 curr_vol_left = inb(portbase + 1);
02330fba
AM
509
510 /* take care of muting flag contained in left channel */
511 if (curr_vol_left & AZF_MUTE_BIT)
512 dst_vol_left |= AZF_MUTE_BIT;
513 else
514 dst_vol_left &= ~AZF_MUTE_BIT;
515
516 left_change = (curr_vol_left > dst_vol_left) ? -1 : 1;
517 }
518
519 if (chan_sel & SET_CHAN_RIGHT) {
d91c64c8 520 curr_vol_right = inb(portbase + 0);
02330fba
AM
521
522 right_change = (curr_vol_right > dst_vol_right) ? -1 : 1;
523 }
1da177e4 524
e2f87260 525 do {
02330fba
AM
526 if (left_change) {
527 if (curr_vol_left != dst_vol_left) {
528 curr_vol_left += left_change;
529 outb(curr_vol_left, portbase + 1);
530 } else
531 left_change = 0;
1da177e4 532 }
02330fba
AM
533 if (right_change) {
534 if (curr_vol_right != dst_vol_right) {
535 curr_vol_right += right_change;
536
1da177e4
LT
537 /* during volume change, the right channel is crackling
538 * somewhat more than the left channel, unfortunately.
539 * This seems to be a hardware issue. */
02330fba
AM
540 outb(curr_vol_right, portbase + 0);
541 } else
542 right_change = 0;
1da177e4
LT
543 }
544 if (delay)
545 mdelay(delay);
02330fba 546 } while ((left_change) || (right_change));
1da177e4
LT
547 snd_azf3328_dbgcallleave();
548}
549
550/*
551 * general mixer element
552 */
95de7766 553struct azf3328_mixer_reg {
02330fba 554 unsigned reg;
1da177e4
LT
555 unsigned int lchan_shift, rchan_shift;
556 unsigned int mask;
557 unsigned int invert: 1;
558 unsigned int stereo: 1;
559 unsigned int enum_c: 4;
95de7766 560};
1da177e4
LT
561
562#define COMPOSE_MIXER_REG(reg,lchan_shift,rchan_shift,mask,invert,stereo,enum_c) \
d91c64c8
AM
563 ((reg) | (lchan_shift << 8) | (rchan_shift << 12) | \
564 (mask << 16) | \
565 (invert << 24) | \
566 (stereo << 25) | \
567 (enum_c << 26))
1da177e4 568
95de7766 569static void snd_azf3328_mixer_reg_decode(struct azf3328_mixer_reg *r, unsigned long val)
1da177e4
LT
570{
571 r->reg = val & 0xff;
572 r->lchan_shift = (val >> 8) & 0x0f;
573 r->rchan_shift = (val >> 12) & 0x0f;
574 r->mask = (val >> 16) & 0xff;
575 r->invert = (val >> 24) & 1;
576 r->stereo = (val >> 25) & 1;
577 r->enum_c = (val >> 26) & 0x0f;
578}
579
580/*
581 * mixer switches/volumes
582 */
583
584#define AZF3328_MIXER_SWITCH(xname, reg, shift, invert) \
585{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
586 .info = snd_azf3328_info_mixer, \
587 .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \
588 .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0x1, invert, 0, 0), \
589}
590
591#define AZF3328_MIXER_VOL_STEREO(xname, reg, mask, invert) \
592{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
593 .info = snd_azf3328_info_mixer, \
594 .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \
595 .private_value = COMPOSE_MIXER_REG(reg, 8, 0, mask, invert, 1, 0), \
596}
597
598#define AZF3328_MIXER_VOL_MONO(xname, reg, mask, is_right_chan) \
599{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
600 .info = snd_azf3328_info_mixer, \
601 .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \
602 .private_value = COMPOSE_MIXER_REG(reg, is_right_chan ? 0 : 8, 0, mask, 1, 0, 0), \
603}
604
605#define AZF3328_MIXER_VOL_SPECIAL(xname, reg, mask, shift, invert) \
606{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
607 .info = snd_azf3328_info_mixer, \
608 .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \
609 .private_value = COMPOSE_MIXER_REG(reg, shift, 0, mask, invert, 0, 0), \
610}
611
612#define AZF3328_MIXER_ENUM(xname, reg, enum_c, shift) \
613{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
614 .info = snd_azf3328_info_mixer_enum, \
615 .get = snd_azf3328_get_mixer_enum, .put = snd_azf3328_put_mixer_enum, \
616 .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0, 0, 0, enum_c), \
617}
618
d91c64c8 619static int
95de7766
TI
620snd_azf3328_info_mixer(struct snd_kcontrol *kcontrol,
621 struct snd_ctl_elem_info *uinfo)
1da177e4 622{
95de7766 623 struct azf3328_mixer_reg reg;
1da177e4
LT
624
625 snd_azf3328_dbgcallenter();
626 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
d91c64c8
AM
627 uinfo->type = reg.mask == 1 ?
628 SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1da177e4
LT
629 uinfo->count = reg.stereo + 1;
630 uinfo->value.integer.min = 0;
631 uinfo->value.integer.max = reg.mask;
632 snd_azf3328_dbgcallleave();
633 return 0;
634}
635
d91c64c8 636static int
95de7766
TI
637snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol,
638 struct snd_ctl_elem_value *ucontrol)
1da177e4 639{
95de7766
TI
640 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
641 struct azf3328_mixer_reg reg;
dfbf9511 642 u16 oreg, val;
1da177e4
LT
643
644 snd_azf3328_dbgcallenter();
645 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
646
d91c64c8 647 oreg = snd_azf3328_mixer_inw(chip, reg.reg);
1da177e4
LT
648 val = (oreg >> reg.lchan_shift) & reg.mask;
649 if (reg.invert)
650 val = reg.mask - val;
651 ucontrol->value.integer.value[0] = val;
652 if (reg.stereo) {
653 val = (oreg >> reg.rchan_shift) & reg.mask;
654 if (reg.invert)
655 val = reg.mask - val;
656 ucontrol->value.integer.value[1] = val;
657 }
d91c64c8
AM
658 snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx "
659 "(shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n",
660 reg.reg, oreg,
661 ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],
662 reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo);
1da177e4
LT
663 snd_azf3328_dbgcallleave();
664 return 0;
665}
666
d91c64c8 667static int
95de7766
TI
668snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol,
669 struct snd_ctl_elem_value *ucontrol)
1da177e4 670{
95de7766
TI
671 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
672 struct azf3328_mixer_reg reg;
dfbf9511 673 u16 oreg, nreg, val;
1da177e4
LT
674
675 snd_azf3328_dbgcallenter();
676 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
d91c64c8 677 oreg = snd_azf3328_mixer_inw(chip, reg.reg);
1da177e4
LT
678 val = ucontrol->value.integer.value[0] & reg.mask;
679 if (reg.invert)
680 val = reg.mask - val;
681 nreg = oreg & ~(reg.mask << reg.lchan_shift);
682 nreg |= (val << reg.lchan_shift);
683 if (reg.stereo) {
684 val = ucontrol->value.integer.value[1] & reg.mask;
685 if (reg.invert)
686 val = reg.mask - val;
687 nreg &= ~(reg.mask << reg.rchan_shift);
688 nreg |= (val << reg.rchan_shift);
689 }
690 if (reg.mask >= 0x07) /* it's a volume control, so better take care */
d91c64c8
AM
691 snd_azf3328_mixer_write_volume_gradually(
692 chip, reg.reg, nreg >> 8, nreg & 0xff,
693 /* just set both channels, doesn't matter */
694 SET_CHAN_LEFT|SET_CHAN_RIGHT,
695 0);
1da177e4 696 else
d91c64c8 697 snd_azf3328_mixer_outw(chip, reg.reg, nreg);
1da177e4 698
d91c64c8
AM
699 snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, "
700 "oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n",
701 reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],
702 oreg, reg.lchan_shift, reg.rchan_shift,
703 nreg, snd_azf3328_mixer_inw(chip, reg.reg));
1da177e4
LT
704 snd_azf3328_dbgcallleave();
705 return (nreg != oreg);
706}
707
d91c64c8 708static int
95de7766
TI
709snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,
710 struct snd_ctl_elem_info *uinfo)
1da177e4 711{
d91c64c8 712 static const char * const texts1[] = {
13769e3f 713 "Mic1", "Mic2"
d91c64c8
AM
714 };
715 static const char * const texts2[] = {
13769e3f 716 "Mix", "Mic"
d91c64c8
AM
717 };
718 static const char * const texts3[] = {
02330fba 719 "Mic", "CD", "Video", "Aux",
d91c64c8 720 "Line", "Mix", "Mix Mono", "Phone"
1da177e4 721 };
13769e3f
AM
722 static const char * const texts4[] = {
723 "pre 3D", "post 3D"
724 };
95de7766 725 struct azf3328_mixer_reg reg;
627d3e7a 726 const char * const *p = NULL;
1da177e4
LT
727
728 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
729 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
730 uinfo->count = (reg.reg == IDX_MIXER_REC_SELECT) ? 2 : 1;
731 uinfo->value.enumerated.items = reg.enum_c;
732 if (uinfo->value.enumerated.item > reg.enum_c - 1U)
733 uinfo->value.enumerated.item = reg.enum_c - 1U;
e2f87260 734 if (reg.reg == IDX_MIXER_ADVCTL2) {
13769e3f
AM
735 switch(reg.lchan_shift) {
736 case 8: /* modem out sel */
627d3e7a 737 p = texts1;
13769e3f
AM
738 break;
739 case 9: /* mono sel source */
627d3e7a 740 p = texts2;
13769e3f
AM
741 break;
742 case 15: /* PCM Out Path */
627d3e7a 743 p = texts4;
13769e3f
AM
744 break;
745 }
e2f87260 746 } else
02330fba 747 if (reg.reg == IDX_MIXER_REC_SELECT)
627d3e7a 748 p = texts3;
02330fba 749
627d3e7a 750 strcpy(uinfo->value.enumerated.name, p[uinfo->value.enumerated.item]);
1da177e4
LT
751 return 0;
752}
753
d91c64c8 754static int
95de7766
TI
755snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol,
756 struct snd_ctl_elem_value *ucontrol)
1da177e4 757{
95de7766
TI
758 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
759 struct azf3328_mixer_reg reg;
1da177e4 760 unsigned short val;
02330fba 761
1da177e4 762 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
d91c64c8 763 val = snd_azf3328_mixer_inw(chip, reg.reg);
e2f87260 764 if (reg.reg == IDX_MIXER_REC_SELECT) {
1da177e4
LT
765 ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1);
766 ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1);
e2f87260 767 } else
1da177e4 768 ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1);
d91c64c8
AM
769
770 snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n",
771 reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1],
772 reg.lchan_shift, reg.enum_c);
1da177e4
LT
773 return 0;
774}
775
d91c64c8 776static int
95de7766
TI
777snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
778 struct snd_ctl_elem_value *ucontrol)
1da177e4 779{
95de7766
TI
780 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
781 struct azf3328_mixer_reg reg;
dfbf9511 782 u16 oreg, nreg, val;
02330fba 783
1da177e4 784 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
d91c64c8 785 oreg = snd_azf3328_mixer_inw(chip, reg.reg);
1da177e4 786 val = oreg;
e2f87260 787 if (reg.reg == IDX_MIXER_REC_SELECT) {
1da177e4
LT
788 if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U ||
789 ucontrol->value.enumerated.item[1] > reg.enum_c - 1U)
790 return -EINVAL;
791 val = (ucontrol->value.enumerated.item[0] << 8) |
792 (ucontrol->value.enumerated.item[1] << 0);
e2f87260 793 } else {
1da177e4
LT
794 if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U)
795 return -EINVAL;
796 val &= ~((reg.enum_c - 1) << reg.lchan_shift);
797 val |= (ucontrol->value.enumerated.item[0] << reg.lchan_shift);
798 }
d91c64c8 799 snd_azf3328_mixer_outw(chip, reg.reg, val);
1da177e4
LT
800 nreg = val;
801
802 snd_azf3328_dbgmixer("put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg);
803 return (nreg != oreg);
804}
805
1b60f6b0 806static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
1da177e4
LT
807 AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
808 AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
627d3e7a
AM
809 AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
810 AZF3328_MIXER_VOL_STEREO("PCM Playback Volume",
811 IDX_MIXER_WAVEOUT, 0x1f, 1),
812 AZF3328_MIXER_SWITCH("PCM 3D Bypass Playback Switch",
813 IDX_MIXER_ADVCTL2, 7, 1),
1da177e4
LT
814 AZF3328_MIXER_SWITCH("FM Playback Switch", IDX_MIXER_FMSYNTH, 15, 1),
815 AZF3328_MIXER_VOL_STEREO("FM Playback Volume", IDX_MIXER_FMSYNTH, 0x1f, 1),
816 AZF3328_MIXER_SWITCH("CD Playback Switch", IDX_MIXER_CDAUDIO, 15, 1),
817 AZF3328_MIXER_VOL_STEREO("CD Playback Volume", IDX_MIXER_CDAUDIO, 0x1f, 1),
818 AZF3328_MIXER_SWITCH("Capture Switch", IDX_MIXER_REC_VOLUME, 15, 1),
819 AZF3328_MIXER_VOL_STEREO("Capture Volume", IDX_MIXER_REC_VOLUME, 0x0f, 0),
820 AZF3328_MIXER_ENUM("Capture Source", IDX_MIXER_REC_SELECT, 8, 0),
821 AZF3328_MIXER_SWITCH("Mic Playback Switch", IDX_MIXER_MIC, 15, 1),
822 AZF3328_MIXER_VOL_MONO("Mic Playback Volume", IDX_MIXER_MIC, 0x1f, 1),
823 AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0),
824 AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1),
825 AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1),
d91c64c8
AM
826 AZF3328_MIXER_SWITCH("PC Speaker Playback Switch", IDX_MIXER_PCBEEP, 15, 1),
827 AZF3328_MIXER_VOL_SPECIAL("PC Speaker Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1),
1da177e4
LT
828 AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1),
829 AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1),
830 AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1),
831 AZF3328_MIXER_VOL_STEREO("Aux Playback Volume", IDX_MIXER_AUX, 0x1f, 1),
832 AZF3328_MIXER_SWITCH("Modem Playback Switch", IDX_MIXER_MODEMOUT, 15, 1),
833 AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1),
834 AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1),
835 AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1),
13769e3f
AM
836 AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8),
837 AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9),
e24a121a 838 AZF3328_MIXER_ENUM("PCM Output Route", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */
1da177e4
LT
839 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0),
840 AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0),
d91c64c8 841 AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0),
13769e3f
AM
842 AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */
843 AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */
1da177e4
LT
844#if MIXER_TESTING
845 AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0),
846 AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0),
847 AZF3328_MIXER_SWITCH("2", IDX_MIXER_ADVCTL2, 2, 0),
848 AZF3328_MIXER_SWITCH("3", IDX_MIXER_ADVCTL2, 3, 0),
849 AZF3328_MIXER_SWITCH("4", IDX_MIXER_ADVCTL2, 4, 0),
850 AZF3328_MIXER_SWITCH("5", IDX_MIXER_ADVCTL2, 5, 0),
851 AZF3328_MIXER_SWITCH("6", IDX_MIXER_ADVCTL2, 6, 0),
852 AZF3328_MIXER_SWITCH("7", IDX_MIXER_ADVCTL2, 7, 0),
853 AZF3328_MIXER_SWITCH("8", IDX_MIXER_ADVCTL2, 8, 0),
854 AZF3328_MIXER_SWITCH("9", IDX_MIXER_ADVCTL2, 9, 0),
855 AZF3328_MIXER_SWITCH("10", IDX_MIXER_ADVCTL2, 10, 0),
856 AZF3328_MIXER_SWITCH("11", IDX_MIXER_ADVCTL2, 11, 0),
857 AZF3328_MIXER_SWITCH("12", IDX_MIXER_ADVCTL2, 12, 0),
858 AZF3328_MIXER_SWITCH("13", IDX_MIXER_ADVCTL2, 13, 0),
859 AZF3328_MIXER_SWITCH("14", IDX_MIXER_ADVCTL2, 14, 0),
860 AZF3328_MIXER_SWITCH("15", IDX_MIXER_ADVCTL2, 15, 0),
861#endif
862};
863
1b60f6b0 864static u16 __devinitdata snd_azf3328_init_values[][2] = {
1da177e4
LT
865 { IDX_MIXER_PLAY_MASTER, MIXER_MUTE_MASK|0x1f1f },
866 { IDX_MIXER_MODEMOUT, MIXER_MUTE_MASK|0x1f1f },
867 { IDX_MIXER_BASSTREBLE, 0x0000 },
868 { IDX_MIXER_PCBEEP, MIXER_MUTE_MASK|0x1f1f },
869 { IDX_MIXER_MODEMIN, MIXER_MUTE_MASK|0x1f1f },
870 { IDX_MIXER_MIC, MIXER_MUTE_MASK|0x001f },
871 { IDX_MIXER_LINEIN, MIXER_MUTE_MASK|0x1f1f },
872 { IDX_MIXER_CDAUDIO, MIXER_MUTE_MASK|0x1f1f },
873 { IDX_MIXER_VIDEO, MIXER_MUTE_MASK|0x1f1f },
874 { IDX_MIXER_AUX, MIXER_MUTE_MASK|0x1f1f },
875 { IDX_MIXER_WAVEOUT, MIXER_MUTE_MASK|0x1f1f },
876 { IDX_MIXER_FMSYNTH, MIXER_MUTE_MASK|0x1f1f },
877 { IDX_MIXER_REC_VOLUME, MIXER_MUTE_MASK|0x0707 },
878};
879
d91c64c8 880static int __devinit
95de7766 881snd_azf3328_mixer_new(struct snd_azf3328 *chip)
1da177e4 882{
95de7766
TI
883 struct snd_card *card;
884 const struct snd_kcontrol_new *sw;
1da177e4
LT
885 unsigned int idx;
886 int err;
887
888 snd_azf3328_dbgcallenter();
da3cec35
TI
889 if (snd_BUG_ON(!chip || !chip->card))
890 return -EINVAL;
1da177e4
LT
891
892 card = chip->card;
893
894 /* mixer reset */
d91c64c8 895 snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
1da177e4
LT
896
897 /* mute and zero volume channels */
02330fba 898 for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); ++idx) {
d91c64c8
AM
899 snd_azf3328_mixer_outw(chip,
900 snd_azf3328_init_values[idx][0],
901 snd_azf3328_init_values[idx][1]);
1da177e4 902 }
02330fba 903
1da177e4
LT
904 /* add mixer controls */
905 sw = snd_azf3328_mixer_controls;
02330fba
AM
906 for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls);
907 ++idx, ++sw) {
1da177e4
LT
908 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip))) < 0)
909 return err;
910 }
911 snd_component_add(card, "AZF3328 mixer");
912 strcpy(card->mixername, "AZF3328 mixer");
913
914 snd_azf3328_dbgcallleave();
915 return 0;
916}
917
d91c64c8 918static int
95de7766
TI
919snd_azf3328_hw_params(struct snd_pcm_substream *substream,
920 struct snd_pcm_hw_params *hw_params)
1da177e4
LT
921{
922 int res;
923 snd_azf3328_dbgcallenter();
924 res = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
925 snd_azf3328_dbgcallleave();
926 return res;
927}
928
d91c64c8 929static int
95de7766 930snd_azf3328_hw_free(struct snd_pcm_substream *substream)
1da177e4
LT
931{
932 snd_azf3328_dbgcallenter();
933 snd_pcm_lib_free_pages(substream);
934 snd_azf3328_dbgcallleave();
935 return 0;
936}
937
d91c64c8 938static void
02330fba 939snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
dfbf9511 940 enum snd_azf3328_codec_type codec_type,
627d3e7a 941 enum azf_freq_t bitrate,
1da177e4
LT
942 unsigned int format_width,
943 unsigned int channels
944)
945{
1da177e4 946 unsigned long flags;
dfbf9511
AM
947 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
948 u16 val = 0xff00;
1da177e4
LT
949
950 snd_azf3328_dbgcallenter();
951 switch (bitrate) {
02330fba
AM
952 case AZF_FREQ_4000: val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break;
953 case AZF_FREQ_4800: val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break;
954 case AZF_FREQ_5512:
955 /* the AZF3328 names it "5510" for some strange reason */
956 val |= SOUNDFORMAT_FREQ_5510; break;
957 case AZF_FREQ_6620: val |= SOUNDFORMAT_FREQ_6620; break;
958 case AZF_FREQ_8000: val |= SOUNDFORMAT_FREQ_8000; break;
959 case AZF_FREQ_9600: val |= SOUNDFORMAT_FREQ_9600; break;
960 case AZF_FREQ_11025: val |= SOUNDFORMAT_FREQ_11025; break;
961 case AZF_FREQ_13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break;
962 case AZF_FREQ_16000: val |= SOUNDFORMAT_FREQ_16000; break;
963 case AZF_FREQ_22050: val |= SOUNDFORMAT_FREQ_22050; break;
964 case AZF_FREQ_32000: val |= SOUNDFORMAT_FREQ_32000; break;
1da177e4 965 default:
99b359ba 966 snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate);
02330fba
AM
967 /* fall-through */
968 case AZF_FREQ_44100: val |= SOUNDFORMAT_FREQ_44100; break;
969 case AZF_FREQ_48000: val |= SOUNDFORMAT_FREQ_48000; break;
970 case AZF_FREQ_66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break;
1da177e4 971 }
d91c64c8
AM
972 /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */
973 /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */
974 /* val = 0xff0a; 47m30.599s (4764,891Hz; -> 4800Hz???) yup, 4803Hz */
975 /* val = 0xff0c; 57m0.510s (4010,263Hz; -> 4000Hz???) yup, 4003Hz */
1da177e4
LT
976 /* val = 0xff05; 5m11.556s (... -> 44100Hz) */
977 /* val = 0xff03; 10m21.529s (21872,463Hz; -> 22050Hz???) */
978 /* val = 0xff0f; 20m41.883s (10937,993Hz; -> 11025Hz???) */
979 /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */
980 /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */
d91c64c8 981
1da177e4
LT
982 if (channels == 2)
983 val |= SOUNDFORMAT_FLAG_2CHANNELS;
984
985 if (format_width == 16)
986 val |= SOUNDFORMAT_FLAG_16BIT;
987
988 spin_lock_irqsave(&chip->reg_lock, flags);
02330fba 989
1da177e4 990 /* set bitrate/format */
dfbf9511 991 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val);
02330fba 992
1da177e4
LT
993 /* changing the bitrate/format settings switches off the
994 * audio output with an annoying click in case of 8/16bit format change
995 * (maybe shutting down DAC/ADC?), thus immediately
996 * do some tweaking to reenable it and get rid of the clicking
997 * (FIXME: yes, it works, but what exactly am I doing here?? :)
998 * FIXME: does this have some side effects for full-duplex
999 * or other dramatic side effects? */
dfbf9511
AM
1000 if (codec_type == AZF_CODEC_PLAYBACK) /* only do it for playback */
1001 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1002 snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) |
1003 DMA_RUN_SOMETHING1 |
1004 DMA_RUN_SOMETHING2 |
d91c64c8
AM
1005 SOMETHING_ALMOST_ALWAYS_SET |
1006 DMA_EPILOGUE_SOMETHING |
1007 DMA_SOMETHING_ELSE
1008 );
1da177e4
LT
1009
1010 spin_unlock_irqrestore(&chip->reg_lock, flags);
1011 snd_azf3328_dbgcallleave();
1012}
1013
02330fba
AM
1014static inline void
1015snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip,
dfbf9511 1016 enum snd_azf3328_codec_type codec_type
02330fba
AM
1017)
1018{
1019 /* choose lowest frequency for low power consumption.
1020 * While this will cause louder noise due to rather coarse frequency,
1021 * it should never matter since output should always
1022 * get disabled properly when idle anyway. */
dfbf9511 1023 snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1);
02330fba
AM
1024}
1025
627d3e7a 1026static void
dfbf9511 1027snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip,
627d3e7a 1028 unsigned bitmask,
dfbf9511 1029 bool enable
627d3e7a
AM
1030)
1031{
1032 if (enable)
dfbf9511 1033 chip->shadow_reg_ctrl_6AH &= ~bitmask;
627d3e7a 1034 else
dfbf9511 1035 chip->shadow_reg_ctrl_6AH |= bitmask;
627d3e7a 1036 snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n",
dfbf9511
AM
1037 bitmask, enable, chip->shadow_reg_ctrl_6AH);
1038 snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH);
627d3e7a
AM
1039}
1040
02330fba 1041static inline void
dfbf9511 1042snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable)
02330fba 1043{
627d3e7a 1044 snd_azf3328_dbgplay("codec_enable %d\n", enable);
02330fba
AM
1045 /* no idea what exactly is being done here, but I strongly assume it's
1046 * PM related */
dfbf9511 1047 snd_azf3328_ctrl_reg_6AH_update(
627d3e7a 1048 chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable
02330fba
AM
1049 );
1050}
1051
1052static void
dfbf9511
AM
1053snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip,
1054 enum snd_azf3328_codec_type codec_type,
1055 bool enable
02330fba
AM
1056)
1057{
dfbf9511
AM
1058 struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1059 bool need_change = (codec->running != enable);
02330fba
AM
1060
1061 snd_azf3328_dbgplay(
dfbf9511
AM
1062 "codec_activity: %s codec, enable %d, need_change %d\n",
1063 codec->name, enable, need_change
02330fba
AM
1064 );
1065 if (need_change) {
dfbf9511
AM
1066 static const struct {
1067 enum snd_azf3328_codec_type other1;
1068 enum snd_azf3328_codec_type other2;
1069 } peer_codecs[3] =
1070 { { AZF_CODEC_CAPTURE, AZF_CODEC_I2S_OUT },
1071 { AZF_CODEC_PLAYBACK, AZF_CODEC_I2S_OUT },
1072 { AZF_CODEC_PLAYBACK, AZF_CODEC_CAPTURE } };
1073 bool call_function;
1074
1075 if (enable)
1076 /* if enable codec, call enable_codecs func
1077 to enable codec supply... */
1078 call_function = 1;
1079 else {
1080 /* ...otherwise call enable_codecs func
1081 (which globally shuts down operation of codecs)
1082 only in case the other codecs are currently
1083 not active either! */
1084 if ((!chip->codecs[peer_codecs[codec_type].other1]
1085 .running)
1086 && (!chip->codecs[peer_codecs[codec_type].other2]
1087 .running))
1088 call_function = 1;
1089 }
1090 if (call_function)
1091 snd_azf3328_ctrl_enable_codecs(chip, enable);
02330fba
AM
1092
1093 /* ...and adjust clock, too
1094 * (reduce noise and power consumption) */
1095 if (!enable)
1096 snd_azf3328_codec_setfmt_lowpower(
1097 chip,
dfbf9511 1098 codec_type
02330fba
AM
1099 );
1100 }
dfbf9511 1101 codec->running = enable;
02330fba
AM
1102}
1103
d91c64c8 1104static void
dfbf9511
AM
1105snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
1106 enum snd_azf3328_codec_type codec_type,
1107 unsigned long addr,
1108 unsigned int count,
1109 unsigned int size
02330fba 1110)
1da177e4 1111{
dfbf9511 1112 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1da177e4 1113 snd_azf3328_dbgcallenter();
dfbf9511
AM
1114 if (!codec->running) {
1115 /* AZF3328 uses a two buffer pointer DMA transfer approach */
02330fba 1116
dfbf9511 1117 unsigned long flags;
02330fba
AM
1118
1119 /* width 32bit (prevent overflow): */
dfbf9511 1120 u32 addr_area2, count_areas, lengths;
d91c64c8 1121
d91c64c8
AM
1122 count_areas = size/2;
1123 addr_area2 = addr+count_areas;
1124 count_areas--; /* max. index */
1125 snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas);
1126
1127 /* build combined I/O buffer length word */
dfbf9511 1128 lengths = (count_areas << 16) | (count_areas);
1da177e4 1129 spin_lock_irqsave(&chip->reg_lock, flags);
dfbf9511
AM
1130 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr);
1131 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2,
1132 addr_area2);
1133 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS,
1134 lengths);
1da177e4
LT
1135 spin_unlock_irqrestore(&chip->reg_lock, flags);
1136 }
1137 snd_azf3328_dbgcallleave();
1138}
1139
d91c64c8 1140static int
dfbf9511 1141snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)
1da177e4
LT
1142{
1143#if 0
95de7766
TI
1144 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1145 struct snd_pcm_runtime *runtime = substream->runtime;
1da177e4
LT
1146 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1147 unsigned int count = snd_pcm_lib_period_bytes(substream);
1148#endif
1149
1150 snd_azf3328_dbgcallenter();
1151#if 0
dfbf9511 1152 snd_azf3328_codec_setfmt(chip, AZF_CODEC_...,
d91c64c8
AM
1153 runtime->rate,
1154 snd_pcm_format_width(runtime->format),
1155 runtime->channels);
dfbf9511
AM
1156 snd_azf3328_codec_setdmaa(chip, AZF_CODEC_...,
1157 runtime->dma_addr, count, size);
1da177e4
LT
1158#endif
1159 snd_azf3328_dbgcallleave();
1160 return 0;
1161}
1162
d91c64c8 1163static int
dfbf9511
AM
1164snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1165 struct snd_pcm_substream *substream, int cmd)
1da177e4 1166{
95de7766 1167 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
dfbf9511 1168 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
95de7766 1169 struct snd_pcm_runtime *runtime = substream->runtime;
1da177e4 1170 int result = 0;
dfbf9511
AM
1171 u16 flags1;
1172 bool previously_muted = 0;
1173 bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type);
1da177e4 1174
dfbf9511 1175 snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd);
d91c64c8 1176
1da177e4
LT
1177 switch (cmd) {
1178 case SNDRV_PCM_TRIGGER_START:
dfbf9511
AM
1179 snd_azf3328_dbgplay("START %s\n", codec->name);
1180
1181 if (is_playback_codec) {
1182 /* mute WaveOut (avoid clicking during setup) */
1183 previously_muted =
1184 snd_azf3328_mixer_set_mute(
1185 chip, IDX_MIXER_WAVEOUT, 1
1186 );
1187 }
1da177e4 1188
dfbf9511 1189 snd_azf3328_codec_setfmt(chip, codec_type,
d91c64c8
AM
1190 runtime->rate,
1191 snd_pcm_format_width(runtime->format),
1192 runtime->channels);
1da177e4
LT
1193
1194 spin_lock(&chip->reg_lock);
02330fba 1195 /* first, remember current value: */
dfbf9511 1196 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
02330fba 1197
dfbf9511
AM
1198 /* stop transfer */
1199 flags1 &= ~DMA_RESUME;
1200 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
02330fba 1201
1da177e4 1202 /* FIXME: clear interrupts or what??? */
dfbf9511 1203 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff);
1da177e4
LT
1204 spin_unlock(&chip->reg_lock);
1205
dfbf9511 1206 snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr,
d91c64c8 1207 snd_pcm_lib_period_bytes(substream),
dfbf9511
AM
1208 snd_pcm_lib_buffer_bytes(substream)
1209 );
1da177e4
LT
1210
1211 spin_lock(&chip->reg_lock);
1212#ifdef WIN9X
1213 /* FIXME: enable playback/recording??? */
dfbf9511
AM
1214 flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2;
1215 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1da177e4 1216
dfbf9511 1217 /* start transfer again */
1da177e4 1218 /* FIXME: what is this value (0x0010)??? */
dfbf9511
AM
1219 flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;
1220 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1da177e4 1221#else /* NT4 */
dfbf9511 1222 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
d91c64c8 1223 0x0000);
dfbf9511
AM
1224 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1225 DMA_RUN_SOMETHING1);
1226 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1227 DMA_RUN_SOMETHING1 |
1228 DMA_RUN_SOMETHING2);
1229 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
d91c64c8
AM
1230 DMA_RESUME |
1231 SOMETHING_ALMOST_ALWAYS_SET |
1232 DMA_EPILOGUE_SOMETHING |
1233 DMA_SOMETHING_ELSE);
1da177e4
LT
1234#endif
1235 spin_unlock(&chip->reg_lock);
dfbf9511
AM
1236 snd_azf3328_ctrl_codec_activity(chip, codec_type, 1);
1237
1238 if (is_playback_codec) {
1239 /* now unmute WaveOut */
1240 if (!previously_muted)
1241 snd_azf3328_mixer_set_mute(
1242 chip, IDX_MIXER_WAVEOUT, 0
1243 );
1244 }
1da177e4 1245
dfbf9511 1246 snd_azf3328_dbgplay("STARTED %s\n", codec->name);
1da177e4 1247 break;
ca54bde3 1248 case SNDRV_PCM_TRIGGER_RESUME:
dfbf9511
AM
1249 snd_azf3328_dbgplay("RESUME %s\n", codec->name);
1250 /* resume codec if we were active */
02330fba 1251 spin_lock(&chip->reg_lock);
dfbf9511
AM
1252 if (codec->running)
1253 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1254 snd_azf3328_codec_inw(
1255 codec, IDX_IO_CODEC_DMA_FLAGS
1256 ) | DMA_RESUME
1257 );
02330fba 1258 spin_unlock(&chip->reg_lock);
ca54bde3 1259 break;
d91c64c8 1260 case SNDRV_PCM_TRIGGER_STOP:
dfbf9511
AM
1261 snd_azf3328_dbgplay("STOP %s\n", codec->name);
1262
1263 if (is_playback_codec) {
1264 /* mute WaveOut (avoid clicking during setup) */
1265 previously_muted =
1266 snd_azf3328_mixer_set_mute(
1267 chip, IDX_MIXER_WAVEOUT, 1
1268 );
1269 }
1da177e4
LT
1270
1271 spin_lock(&chip->reg_lock);
02330fba 1272 /* first, remember current value: */
dfbf9511 1273 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
1da177e4 1274
dfbf9511
AM
1275 /* stop transfer */
1276 flags1 &= ~DMA_RESUME;
1277 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1da177e4 1278
d91c64c8
AM
1279 /* hmm, is this really required? we're resetting the same bit
1280 * immediately thereafter... */
dfbf9511
AM
1281 flags1 |= DMA_RUN_SOMETHING1;
1282 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1da177e4 1283
dfbf9511
AM
1284 flags1 &= ~DMA_RUN_SOMETHING1;
1285 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1da177e4 1286 spin_unlock(&chip->reg_lock);
dfbf9511
AM
1287 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
1288
1289 if (is_playback_codec) {
1290 /* now unmute WaveOut */
1291 if (!previously_muted)
1292 snd_azf3328_mixer_set_mute(
1293 chip, IDX_MIXER_WAVEOUT, 0
1294 );
1295 }
02330fba 1296
dfbf9511 1297 snd_azf3328_dbgplay("STOPPED %s\n", codec->name);
1da177e4 1298 break;
ca54bde3 1299 case SNDRV_PCM_TRIGGER_SUSPEND:
dfbf9511
AM
1300 snd_azf3328_dbgplay("SUSPEND %s\n", codec->name);
1301 /* make sure codec is stopped */
1302 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1303 snd_azf3328_codec_inw(
1304 codec, IDX_IO_CODEC_DMA_FLAGS
1305 ) & ~DMA_RESUME
1306 );
ca54bde3 1307 break;
1da177e4 1308 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
99b359ba 1309 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
1da177e4
LT
1310 break;
1311 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
99b359ba 1312 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
1da177e4
LT
1313 break;
1314 default:
ca54bde3 1315 printk(KERN_ERR "FIXME: unknown trigger mode!\n");
1da177e4
LT
1316 return -EINVAL;
1317 }
02330fba 1318
1da177e4
LT
1319 snd_azf3328_dbgcallleave();
1320 return result;
1321}
1322
d91c64c8 1323static int
dfbf9511 1324snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd)
1da177e4 1325{
dfbf9511
AM
1326 return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd);
1327}
02330fba 1328
dfbf9511
AM
1329static int
1330snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1331{
1332 return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd);
1333}
02330fba 1334
dfbf9511
AM
1335static int
1336snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd)
1337{
1338 return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd);
1da177e4
LT
1339}
1340
d91c64c8 1341static snd_pcm_uframes_t
dfbf9511
AM
1342snd_azf3328_codec_pointer(struct snd_pcm_substream *substream,
1343 enum snd_azf3328_codec_type codec_type
1344)
1da177e4 1345{
dfbf9511
AM
1346 const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1347 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
d91c64c8 1348 unsigned long bufptr, result;
1da177e4
LT
1349 snd_pcm_uframes_t frmres;
1350
1351#ifdef QUERY_HARDWARE
dfbf9511 1352 bufptr = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1);
1da177e4
LT
1353#else
1354 bufptr = substream->runtime->dma_addr;
1355#endif
dfbf9511 1356 result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS);
1da177e4 1357
d91c64c8
AM
1358 /* calculate offset */
1359 result -= bufptr;
1360 frmres = bytes_to_frames( substream->runtime, result);
dfbf9511
AM
1361 snd_azf3328_dbgplay("%s @ 0x%8lx, frames %8ld\n",
1362 codec->name, result, frmres);
1da177e4
LT
1363 return frmres;
1364}
1365
d91c64c8 1366static snd_pcm_uframes_t
dfbf9511 1367snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream)
1da177e4 1368{
dfbf9511
AM
1369 return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK);
1370}
1da177e4 1371
dfbf9511
AM
1372static snd_pcm_uframes_t
1373snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream)
1374{
1375 return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE);
1376}
1da177e4 1377
dfbf9511
AM
1378static snd_pcm_uframes_t
1379snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream)
1380{
1381 return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT);
1da177e4
LT
1382}
1383
02330fba
AM
1384/******************************************************************/
1385
1386#ifdef SUPPORT_GAMEPORT
1387static inline void
dfbf9511
AM
1388snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip,
1389 bool enable
1390)
02330fba
AM
1391{
1392 snd_azf3328_io_reg_setb(
1393 chip->game_io+IDX_GAME_HWCONFIG,
1394 GAME_HWCFG_IRQ_ENABLE,
1395 enable
1396 );
1397}
1398
1399static inline void
dfbf9511
AM
1400snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip,
1401 bool enable
1402)
02330fba
AM
1403{
1404 snd_azf3328_io_reg_setb(
1405 chip->game_io+IDX_GAME_HWCONFIG,
1406 GAME_HWCFG_LEGACY_ADDRESS_ENABLE,
1407 enable
1408 );
1409}
1410
dfbf9511
AM
1411static void
1412snd_azf3328_gameport_set_counter_frequency(struct snd_azf3328 *chip,
1413 unsigned int freq_cfg
1414)
1415{
1416 snd_azf3328_io_reg_setb(
1417 chip->game_io+IDX_GAME_HWCONFIG,
1418 0x02,
1419 (freq_cfg & 1) != 0
1420 );
1421 snd_azf3328_io_reg_setb(
1422 chip->game_io+IDX_GAME_HWCONFIG,
1423 0x04,
1424 (freq_cfg & 2) != 0
1425 );
1426}
1427
02330fba 1428static inline void
dfbf9511 1429snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, bool enable)
02330fba 1430{
dfbf9511 1431 snd_azf3328_ctrl_reg_6AH_update(
627d3e7a 1432 chip, IO_6A_SOMETHING2_GAMEPORT, enable
02330fba
AM
1433 );
1434}
1435
1436static inline void
1437snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip)
1438{
1439 /*
1440 * skeleton handler only
1441 * (we do not want axis reading in interrupt handler - too much load!)
1442 */
1443 snd_azf3328_dbggame("gameport irq\n");
1444
1445 /* this should ACK the gameport IRQ properly, hopefully. */
1446 snd_azf3328_game_inw(chip, IDX_GAME_AXIS_VALUE);
1447}
1448
1449static int
1450snd_azf3328_gameport_open(struct gameport *gameport, int mode)
1451{
1452 struct snd_azf3328 *chip = gameport_get_port_data(gameport);
1453 int res;
1454
1455 snd_azf3328_dbggame("gameport_open, mode %d\n", mode);
1456 switch (mode) {
1457 case GAMEPORT_MODE_COOKED:
1458 case GAMEPORT_MODE_RAW:
1459 res = 0;
1460 break;
1461 default:
1462 res = -1;
1463 break;
1464 }
1465
dfbf9511
AM
1466 snd_azf3328_gameport_set_counter_frequency(chip,
1467 GAME_HWCFG_ADC_COUNTER_FREQ_STD);
02330fba
AM
1468 snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0));
1469
1470 return res;
1471}
1472
1473static void
1474snd_azf3328_gameport_close(struct gameport *gameport)
1475{
1476 struct snd_azf3328 *chip = gameport_get_port_data(gameport);
1477
1478 snd_azf3328_dbggame("gameport_close\n");
dfbf9511
AM
1479 snd_azf3328_gameport_set_counter_frequency(chip,
1480 GAME_HWCFG_ADC_COUNTER_FREQ_1_200);
02330fba
AM
1481 snd_azf3328_gameport_axis_circuit_enable(chip, 0);
1482}
1483
1484static int
1485snd_azf3328_gameport_cooked_read(struct gameport *gameport,
1486 int *axes,
1487 int *buttons
1488)
1489{
1490 struct snd_azf3328 *chip = gameport_get_port_data(gameport);
1491 int i;
1492 u8 val;
1493 unsigned long flags;
1494
da3cec35
TI
1495 if (snd_BUG_ON(!chip))
1496 return 0;
02330fba
AM
1497
1498 spin_lock_irqsave(&chip->reg_lock, flags);
1499 val = snd_azf3328_game_inb(chip, IDX_GAME_LEGACY_COMPATIBLE);
1500 *buttons = (~(val) >> 4) & 0xf;
1501
1502 /* ok, this one is a bit dirty: cooked_read is being polled by a timer,
1503 * thus we're atomic and cannot actively wait in here
1504 * (which would be useful for us since it probably would be better
1505 * to trigger a measurement in here, then wait a short amount of
1506 * time until it's finished, then read values of _this_ measurement).
1507 *
1508 * Thus we simply resort to reading values if they're available already
1509 * and trigger the next measurement.
1510 */
1511
1512 val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG);
1513 if (val & GAME_AXES_SAMPLING_READY) {
dfbf9511 1514 for (i = 0; i < ARRAY_SIZE(chip->axes); ++i) {
02330fba
AM
1515 /* configure the axis to read */
1516 val = (i << 4) | 0x0f;
1517 snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val);
1518
1519 chip->axes[i] = snd_azf3328_game_inw(
1520 chip, IDX_GAME_AXIS_VALUE
1521 );
1522 }
1523 }
1524
1525 /* trigger next axes sampling, to be evaluated the next time we
1526 * enter this function */
1527
1528 /* for some very, very strange reason we cannot enable
1529 * Measurement Ready monitoring for all axes here,
1530 * at least not when only one joystick connected */
1531 val = 0x03; /* we're able to monitor axes 1 and 2 only */
1532 snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val);
1533
1534 snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff);
1535 spin_unlock_irqrestore(&chip->reg_lock, flags);
1536
dfbf9511 1537 for (i = 0; i < ARRAY_SIZE(chip->axes); i++) {
02330fba
AM
1538 axes[i] = chip->axes[i];
1539 if (axes[i] == 0xffff)
1540 axes[i] = -1;
1541 }
1542
1543 snd_azf3328_dbggame("cooked_read: axes %d %d %d %d buttons %d\n",
1544 axes[0], axes[1], axes[2], axes[3], *buttons
1545 );
1546
1547 return 0;
1548}
1549
1550static int __devinit
1551snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
1552{
1553 struct gameport *gp;
1554
02330fba
AM
1555 chip->gameport = gp = gameport_allocate_port();
1556 if (!gp) {
1557 printk(KERN_ERR "azt3328: cannot alloc memory for gameport\n");
1558 return -ENOMEM;
1559 }
1560
1561 gameport_set_name(gp, "AZF3328 Gameport");
1562 gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
1563 gameport_set_dev_parent(gp, &chip->pci->dev);
627d3e7a 1564 gp->io = chip->game_io;
02330fba
AM
1565 gameport_set_port_data(gp, chip);
1566
1567 gp->open = snd_azf3328_gameport_open;
1568 gp->close = snd_azf3328_gameport_close;
1569 gp->fuzz = 16; /* seems ok */
1570 gp->cooked_read = snd_azf3328_gameport_cooked_read;
1571
1572 /* DISABLE legacy address: we don't need it! */
1573 snd_azf3328_gameport_legacy_address_enable(chip, 0);
1574
dfbf9511
AM
1575 snd_azf3328_gameport_set_counter_frequency(chip,
1576 GAME_HWCFG_ADC_COUNTER_FREQ_1_200);
02330fba
AM
1577 snd_azf3328_gameport_axis_circuit_enable(chip, 0);
1578
1579 gameport_register_port(chip->gameport);
1580
1581 return 0;
1582}
1583
1584static void
1585snd_azf3328_gameport_free(struct snd_azf3328 *chip)
1586{
1587 if (chip->gameport) {
1588 gameport_unregister_port(chip->gameport);
1589 chip->gameport = NULL;
1590 }
1591 snd_azf3328_gameport_irq_enable(chip, 0);
1592}
1593#else
1594static inline int
1595snd_azf3328_gameport(struct snd_azf3328 *chip, int dev) { return -ENOSYS; }
1596static inline void
1597snd_azf3328_gameport_free(struct snd_azf3328 *chip) { }
1598static inline void
1599snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip)
1600{
1601 printk(KERN_WARNING "huh, game port IRQ occurred!?\n");
1602}
1603#endif /* SUPPORT_GAMEPORT */
1604
1605/******************************************************************/
1606
627d3e7a
AM
1607static inline void
1608snd_azf3328_irq_log_unknown_type(u8 which)
1609{
1610 snd_azf3328_dbgplay(
1611 "azt3328: unknown IRQ type (%x) occurred, please report!\n",
1612 which
1613 );
1614}
1615
dfbf9511
AM
1616static inline void
1617snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status)
1618{
1619 u8 which;
1620 enum snd_azf3328_codec_type codec_type;
1621 const struct snd_azf3328_codec_data *codec;
1622
1623 for (codec_type = AZF_CODEC_PLAYBACK;
1624 codec_type <= AZF_CODEC_I2S_OUT;
1625 ++codec_type) {
1626
1627 /* skip codec if there's no interrupt for it */
1628 if (!(status & (1 << codec_type)))
1629 continue;
1630
1631 codec = &chip->codecs[codec_type];
1632
1633 spin_lock(&chip->reg_lock);
1634 which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE);
1635 /* ack all IRQ types immediately */
1636 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which);
1637 spin_unlock(&chip->reg_lock);
1638
1639 if ((chip->pcm[codec_type])
1640 && (chip->codecs[codec_type].substream)) {
1641 snd_pcm_period_elapsed(
1642 chip->codecs[codec_type].substream
1643 );
1644 snd_azf3328_dbgplay("%s period done (#%x), @ %x\n",
1645 codec->name,
1646 which,
1647 snd_azf3328_codec_inl(
1648 codec, IDX_IO_CODEC_DMA_CURRPOS
1649 )
1650 );
1651 } else
1652 printk(KERN_WARNING "azt3328: irq handler problem!\n");
1653 if (which & IRQ_SOMETHING)
1654 snd_azf3328_irq_log_unknown_type(which);
1655 }
1656}
1657
d91c64c8 1658static irqreturn_t
7d12e780 1659snd_azf3328_interrupt(int irq, void *dev_id)
1da177e4 1660{
95de7766 1661 struct snd_azf3328 *chip = dev_id;
dfbf9511 1662 u8 status;
02330fba 1663#if DEBUG_PLAY_REC
d91c64c8 1664 static unsigned long irq_count;
02330fba 1665#endif
1da177e4 1666
dfbf9511 1667 status = snd_azf3328_ctrl_inb(chip, IDX_IO_IRQSTATUS);
1da177e4
LT
1668
1669 /* fast path out, to ease interrupt sharing */
02330fba 1670 if (!(status &
dfbf9511
AM
1671 (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT
1672 |IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER)
02330fba 1673 ))
1da177e4
LT
1674 return IRQ_NONE; /* must be interrupt for another device */
1675
627d3e7a 1676 snd_azf3328_dbgplay(
dfbf9511 1677 "irq_count %ld! IDX_IO_IRQSTATUS %04x\n",
627d3e7a 1678 irq_count++ /* debug-only */,
627d3e7a
AM
1679 status
1680 );
02330fba 1681
e2f87260 1682 if (status & IRQ_TIMER) {
02330fba
AM
1683 /* snd_azf3328_dbgplay("timer %ld\n",
1684 snd_azf3328_codec_inl(chip, IDX_IO_TIMER_VALUE)
1685 & TIMER_VALUE_MASK
1686 ); */
d91c64c8
AM
1687 if (chip->timer)
1688 snd_timer_interrupt(chip->timer, chip->timer->sticks);
1689 /* ACK timer */
1690 spin_lock(&chip->reg_lock);
dfbf9511 1691 snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07);
d91c64c8
AM
1692 spin_unlock(&chip->reg_lock);
1693 snd_azf3328_dbgplay("azt3328: timer IRQ\n");
1694 }
d91c64c8 1695
dfbf9511
AM
1696 if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT))
1697 snd_azf3328_codec_interrupt(chip, status);
d91c64c8 1698
02330fba
AM
1699 if (status & IRQ_GAMEPORT)
1700 snd_azf3328_gameport_interrupt(chip);
dfbf9511 1701
d91c64c8
AM
1702 /* MPU401 has less critical IRQ requirements
1703 * than timer and playback/recording, right? */
e2f87260 1704 if (status & IRQ_MPU401) {
7d12e780 1705 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
d91c64c8
AM
1706
1707 /* hmm, do we have to ack the IRQ here somehow?
dfbf9511 1708 * If so, then I don't know how yet... */
d91c64c8
AM
1709 snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n");
1710 }
1da177e4
LT
1711 return IRQ_HANDLED;
1712}
1713
1714/*****************************************************************/
1715
dfbf9511
AM
1716/* as long as we think we have identical snd_pcm_hardware parameters
1717 for playback, capture and i2s out, we can use the same physical struct
1718 since the struct is simply being copied into a member.
1719*/
1720static const struct snd_pcm_hardware snd_azf3328_hardware =
1da177e4
LT
1721{
1722 /* FIXME!! Correct? */
d91c64c8
AM
1723 .info = SNDRV_PCM_INFO_MMAP |
1724 SNDRV_PCM_INFO_INTERLEAVED |
1725 SNDRV_PCM_INFO_MMAP_VALID,
1726 .formats = SNDRV_PCM_FMTBIT_S8 |
1727 SNDRV_PCM_FMTBIT_U8 |
1728 SNDRV_PCM_FMTBIT_S16_LE |
1729 SNDRV_PCM_FMTBIT_U16_LE,
1730 .rates = SNDRV_PCM_RATE_5512 |
1731 SNDRV_PCM_RATE_8000_48000 |
1732 SNDRV_PCM_RATE_KNOT,
02330fba
AM
1733 .rate_min = AZF_FREQ_4000,
1734 .rate_max = AZF_FREQ_66200,
1da177e4
LT
1735 .channels_min = 1,
1736 .channels_max = 2,
1737 .buffer_bytes_max = 65536,
1738 .period_bytes_min = 64,
1739 .period_bytes_max = 65536,
1740 .periods_min = 1,
1741 .periods_max = 1024,
1742 /* FIXME: maybe that card actually has a FIFO?
1743 * Hmm, it seems newer revisions do have one, but we still don't know
1744 * its size... */
1745 .fifo_size = 0,
1746};
1747
1da177e4
LT
1748
1749static unsigned int snd_azf3328_fixed_rates[] = {
02330fba
AM
1750 AZF_FREQ_4000,
1751 AZF_FREQ_4800,
1752 AZF_FREQ_5512,
1753 AZF_FREQ_6620,
1754 AZF_FREQ_8000,
1755 AZF_FREQ_9600,
1756 AZF_FREQ_11025,
1757 AZF_FREQ_13240,
1758 AZF_FREQ_16000,
1759 AZF_FREQ_22050,
1760 AZF_FREQ_32000,
1761 AZF_FREQ_44100,
1762 AZF_FREQ_48000,
1763 AZF_FREQ_66200
1764};
1765
95de7766 1766static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = {
02330fba 1767 .count = ARRAY_SIZE(snd_azf3328_fixed_rates),
1da177e4
LT
1768 .list = snd_azf3328_fixed_rates,
1769 .mask = 0,
1770};
1771
1772/*****************************************************************/
1773
d91c64c8 1774static int
dfbf9511
AM
1775snd_azf3328_pcm_open(struct snd_pcm_substream *substream,
1776 enum snd_azf3328_codec_type codec_type
1777)
1da177e4 1778{
95de7766
TI
1779 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1780 struct snd_pcm_runtime *runtime = substream->runtime;
1da177e4
LT
1781
1782 snd_azf3328_dbgcallenter();
dfbf9511
AM
1783 chip->codecs[codec_type].substream = substream;
1784
1785 /* same parameters for all our codecs - at least we think so... */
1786 runtime->hw = snd_azf3328_hardware;
1787
1da177e4
LT
1788 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1789 &snd_azf3328_hw_constraints_rates);
1790 snd_azf3328_dbgcallleave();
1791 return 0;
1792}
1793
dfbf9511
AM
1794static int
1795snd_azf3328_playback_open(struct snd_pcm_substream *substream)
1796{
1797 return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK);
1798}
1799
d91c64c8 1800static int
95de7766 1801snd_azf3328_capture_open(struct snd_pcm_substream *substream)
1da177e4 1802{
dfbf9511
AM
1803 return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE);
1804}
1da177e4 1805
dfbf9511
AM
1806static int
1807snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream)
1808{
1809 return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT);
1da177e4
LT
1810}
1811
d91c64c8 1812static int
dfbf9511
AM
1813snd_azf3328_pcm_close(struct snd_pcm_substream *substream,
1814 enum snd_azf3328_codec_type codec_type
1815)
1da177e4 1816{
95de7766 1817 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1da177e4
LT
1818
1819 snd_azf3328_dbgcallenter();
dfbf9511 1820 chip->codecs[codec_type].substream = NULL;
1da177e4
LT
1821 snd_azf3328_dbgcallleave();
1822 return 0;
1823}
1824
dfbf9511
AM
1825static int
1826snd_azf3328_playback_close(struct snd_pcm_substream *substream)
1827{
1828 return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK);
1829}
1830
d91c64c8 1831static int
95de7766 1832snd_azf3328_capture_close(struct snd_pcm_substream *substream)
1da177e4 1833{
dfbf9511
AM
1834 return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE);
1835}
1da177e4 1836
dfbf9511
AM
1837static int
1838snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream)
1839{
1840 return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT);
1da177e4
LT
1841}
1842
1843/******************************************************************/
1844
95de7766 1845static struct snd_pcm_ops snd_azf3328_playback_ops = {
1da177e4
LT
1846 .open = snd_azf3328_playback_open,
1847 .close = snd_azf3328_playback_close,
1848 .ioctl = snd_pcm_lib_ioctl,
1849 .hw_params = snd_azf3328_hw_params,
1850 .hw_free = snd_azf3328_hw_free,
dfbf9511
AM
1851 .prepare = snd_azf3328_codec_prepare,
1852 .trigger = snd_azf3328_codec_playback_trigger,
1853 .pointer = snd_azf3328_codec_playback_pointer
1da177e4
LT
1854};
1855
95de7766 1856static struct snd_pcm_ops snd_azf3328_capture_ops = {
1da177e4
LT
1857 .open = snd_azf3328_capture_open,
1858 .close = snd_azf3328_capture_close,
1859 .ioctl = snd_pcm_lib_ioctl,
1860 .hw_params = snd_azf3328_hw_params,
1861 .hw_free = snd_azf3328_hw_free,
dfbf9511
AM
1862 .prepare = snd_azf3328_codec_prepare,
1863 .trigger = snd_azf3328_codec_capture_trigger,
1864 .pointer = snd_azf3328_codec_capture_pointer
1865};
1866
1867static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
1868 .open = snd_azf3328_i2s_out_open,
1869 .close = snd_azf3328_i2s_out_close,
1870 .ioctl = snd_pcm_lib_ioctl,
1871 .hw_params = snd_azf3328_hw_params,
1872 .hw_free = snd_azf3328_hw_free,
1873 .prepare = snd_azf3328_codec_prepare,
1874 .trigger = snd_azf3328_codec_i2s_out_trigger,
1875 .pointer = snd_azf3328_codec_i2s_out_pointer
1da177e4
LT
1876};
1877
d91c64c8 1878static int __devinit
dfbf9511 1879snd_azf3328_pcm(struct snd_azf3328 *chip)
1da177e4 1880{
dfbf9511
AM
1881enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */
1882
95de7766 1883 struct snd_pcm *pcm;
1da177e4
LT
1884 int err;
1885
1886 snd_azf3328_dbgcallenter();
dfbf9511
AM
1887
1888 err = snd_pcm_new(chip->card, "AZF3328 DSP", AZF_PCMDEV_STD,
1889 1, 1, &pcm);
1890 if (err < 0)
1da177e4 1891 return err;
dfbf9511
AM
1892 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1893 &snd_azf3328_playback_ops);
1894 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
1895 &snd_azf3328_capture_ops);
1da177e4
LT
1896
1897 pcm->private_data = chip;
1da177e4
LT
1898 pcm->info_flags = 0;
1899 strcpy(pcm->name, chip->card->shortname);
dfbf9511
AM
1900 /* same pcm object for playback/capture (see snd_pcm_new() above) */
1901 chip->pcm[AZF_CODEC_PLAYBACK] = pcm;
1902 chip->pcm[AZF_CODEC_CAPTURE] = pcm;
1da177e4
LT
1903
1904 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
dfbf9511
AM
1905 snd_dma_pci_data(chip->pci),
1906 64*1024, 64*1024);
1907
1908 err = snd_pcm_new(chip->card, "AZF3328 I2S OUT", AZF_PCMDEV_I2S_OUT,
1909 1, 0, &pcm);
1910 if (err < 0)
1911 return err;
1912 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1913 &snd_azf3328_i2s_out_ops);
1914
1915 pcm->private_data = chip;
1916 pcm->info_flags = 0;
1917 strcpy(pcm->name, chip->card->shortname);
1918 chip->pcm[AZF_CODEC_I2S_OUT] = pcm;
1919
1920 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1921 snd_dma_pci_data(chip->pci),
1922 64*1024, 64*1024);
1da177e4
LT
1923
1924 snd_azf3328_dbgcallleave();
1925 return 0;
1926}
1927
1928/******************************************************************/
1929
02330fba
AM
1930/*** NOTE: the physical timer resolution actually is 1024000 ticks per second
1931 *** (probably derived from main crystal via a divider of 24),
d91c64c8
AM
1932 *** but announcing those attributes to user-space would make programs
1933 *** configure the timer to a 1 tick value, resulting in an absolutely fatal
1934 *** timer IRQ storm.
1935 *** Thus I chose to announce a down-scaled virtual timer to the outside and
1936 *** calculate real timer countdown values internally.
1937 *** (the scale factor can be set via module parameter "seqtimer_scaling").
1938 ***/
1939
1940static int
95de7766 1941snd_azf3328_timer_start(struct snd_timer *timer)
d91c64c8 1942{
95de7766 1943 struct snd_azf3328 *chip;
d91c64c8
AM
1944 unsigned long flags;
1945 unsigned int delay;
1946
1947 snd_azf3328_dbgcallenter();
1948 chip = snd_timer_chip(timer);
1949 delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK;
e2f87260 1950 if (delay < 49) {
d91c64c8
AM
1951 /* uhoh, that's not good, since user-space won't know about
1952 * this timing tweak
1953 * (we need to do it to avoid a lockup, though) */
1954
1955 snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay);
1956 delay = 49; /* minimum time is 49 ticks */
1957 }
1958 snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay);
02330fba 1959 delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE;
d91c64c8 1960 spin_lock_irqsave(&chip->reg_lock, flags);
dfbf9511 1961 snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay);
d91c64c8
AM
1962 spin_unlock_irqrestore(&chip->reg_lock, flags);
1963 snd_azf3328_dbgcallleave();
1964 return 0;
1965}
1966
1967static int
95de7766 1968snd_azf3328_timer_stop(struct snd_timer *timer)
d91c64c8 1969{
95de7766 1970 struct snd_azf3328 *chip;
d91c64c8
AM
1971 unsigned long flags;
1972
1973 snd_azf3328_dbgcallenter();
1974 chip = snd_timer_chip(timer);
1975 spin_lock_irqsave(&chip->reg_lock, flags);
1976 /* disable timer countdown and interrupt */
02330fba 1977 /* FIXME: should we write TIMER_IRQ_ACK here? */
dfbf9511 1978 snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0);
d91c64c8
AM
1979 spin_unlock_irqrestore(&chip->reg_lock, flags);
1980 snd_azf3328_dbgcallleave();
1981 return 0;
1982}
1983
1984
1985static int
95de7766 1986snd_azf3328_timer_precise_resolution(struct snd_timer *timer,
d91c64c8
AM
1987 unsigned long *num, unsigned long *den)
1988{
1989 snd_azf3328_dbgcallenter();
1990 *num = 1;
1991 *den = 1024000 / seqtimer_scaling;
1992 snd_azf3328_dbgcallleave();
1993 return 0;
1994}
1995
95de7766 1996static struct snd_timer_hardware snd_azf3328_timer_hw = {
d91c64c8
AM
1997 .flags = SNDRV_TIMER_HW_AUTO,
1998 .resolution = 977, /* 1000000/1024000 = 0.9765625us */
1999 .ticks = 1024000, /* max tick count, defined by the value register; actually it's not 1024000, but 1048576, but we don't care */
2000 .start = snd_azf3328_timer_start,
2001 .stop = snd_azf3328_timer_stop,
2002 .precise_resolution = snd_azf3328_timer_precise_resolution,
2003};
2004
2005static int __devinit
95de7766 2006snd_azf3328_timer(struct snd_azf3328 *chip, int device)
d91c64c8 2007{
95de7766
TI
2008 struct snd_timer *timer = NULL;
2009 struct snd_timer_id tid;
d91c64c8
AM
2010 int err;
2011
2012 snd_azf3328_dbgcallenter();
2013 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
2014 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
2015 tid.card = chip->card->number;
2016 tid.device = device;
2017 tid.subdevice = 0;
2018
2019 snd_azf3328_timer_hw.resolution *= seqtimer_scaling;
2020 snd_azf3328_timer_hw.ticks /= seqtimer_scaling;
02330fba
AM
2021
2022 err = snd_timer_new(chip->card, "AZF3328", &tid, &timer);
2023 if (err < 0)
d91c64c8 2024 goto out;
d91c64c8
AM
2025
2026 strcpy(timer->name, "AZF3328 timer");
2027 timer->private_data = chip;
2028 timer->hw = snd_azf3328_timer_hw;
2029
2030 chip->timer = timer;
2031
02330fba
AM
2032 snd_azf3328_timer_stop(timer);
2033
d91c64c8
AM
2034 err = 0;
2035
2036out:
2037 snd_azf3328_dbgcallleave();
2038 return err;
2039}
2040
2041/******************************************************************/
2042
02330fba
AM
2043static int
2044snd_azf3328_free(struct snd_azf3328 *chip)
2045{
2046 if (chip->irq < 0)
2047 goto __end_hw;
2048
2049 /* reset (close) mixer:
2050 * first mute master volume, then reset
2051 */
2052 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
2053 snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
2054
2055 snd_azf3328_timer_stop(chip->timer);
2056 snd_azf3328_gameport_free(chip);
2057
2058 if (chip->irq >= 0)
2059 synchronize_irq(chip->irq);
2060__end_hw:
2061 if (chip->irq >= 0)
2062 free_irq(chip->irq, chip);
2063 pci_release_regions(chip->pci);
2064 pci_disable_device(chip->pci);
2065
2066 kfree(chip);
2067 return 0;
2068}
2069
2070static int
2071snd_azf3328_dev_free(struct snd_device *device)
2072{
2073 struct snd_azf3328 *chip = device->device_data;
2074 return snd_azf3328_free(chip);
2075}
2076
1da177e4
LT
2077#if 0
2078/* check whether a bit can be modified */
d91c64c8 2079static void
02330fba 2080snd_azf3328_test_bit(unsigned unsigned reg, int bit)
1da177e4
LT
2081{
2082 unsigned char val, valoff, valon;
2083
2084 val = inb(reg);
2085
2086 outb(val & ~(1 << bit), reg);
2087 valoff = inb(reg);
2088
2089 outb(val|(1 << bit), reg);
2090 valon = inb(reg);
02330fba 2091
1da177e4
LT
2092 outb(val, reg);
2093
02330fba
AM
2094 printk(KERN_ERR "reg %04x bit %d: %02x %02x %02x\n",
2095 reg, bit, val, valoff, valon
2096 );
1da177e4
LT
2097}
2098#endif
2099
02330fba 2100static inline void
95de7766 2101snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
d91c64c8 2102{
02330fba 2103#if DEBUG_MISC
d91c64c8
AM
2104 u16 tmp;
2105
02330fba 2106 snd_azf3328_dbgmisc(
dfbf9511 2107 "ctrl_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, "
02330fba 2108 "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n",
dfbf9511 2109 chip->ctrl_io, chip->game_io, chip->mpu_io,
02330fba
AM
2110 chip->opl3_io, chip->mixer_io, chip->irq
2111 );
2112
2113 snd_azf3328_dbgmisc("game %02x %02x %02x %02x %02x %02x\n",
2114 snd_azf3328_game_inb(chip, 0),
2115 snd_azf3328_game_inb(chip, 1),
2116 snd_azf3328_game_inb(chip, 2),
2117 snd_azf3328_game_inb(chip, 3),
2118 snd_azf3328_game_inb(chip, 4),
2119 snd_azf3328_game_inb(chip, 5)
2120 );
2121
2122 for (tmp = 0; tmp < 0x07; tmp += 1)
2123 snd_azf3328_dbgmisc("mpu_io 0x%04x\n", inb(chip->mpu_io + tmp));
2124
2125 for (tmp = 0; tmp <= 0x07; tmp += 1)
2126 snd_azf3328_dbgmisc("0x%02x: game200 0x%04x, game208 0x%04x\n",
2127 tmp, inb(0x200 + tmp), inb(0x208 + tmp));
2128
2129 for (tmp = 0; tmp <= 0x01; tmp += 1)
2130 snd_azf3328_dbgmisc(
2131 "0x%02x: mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, "
2132 "mpu330 0x%04x opl388 0x%04x opl38c 0x%04x\n",
2133 tmp,
2134 inb(0x300 + tmp),
2135 inb(0x310 + tmp),
2136 inb(0x320 + tmp),
2137 inb(0x330 + tmp),
2138 inb(0x388 + tmp),
2139 inb(0x38c + tmp)
2140 );
d91c64c8 2141
dfbf9511
AM
2142 for (tmp = 0; tmp < AZF_IO_SIZE_CTRL; tmp += 2)
2143 snd_azf3328_dbgmisc("ctrl 0x%02x: 0x%04x\n",
2144 tmp, snd_azf3328_ctrl_inw(chip, tmp)
02330fba 2145 );
e24a121a
AM
2146
2147 for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2)
02330fba
AM
2148 snd_azf3328_dbgmisc("mixer 0x%02x: 0x%04x\n",
2149 tmp, snd_azf3328_mixer_inw(chip, tmp)
2150 );
2151#endif /* DEBUG_MISC */
d91c64c8
AM
2152}
2153
2154static int __devinit
95de7766 2155snd_azf3328_create(struct snd_card *card,
02330fba
AM
2156 struct pci_dev *pci,
2157 unsigned long device_type,
2158 struct snd_azf3328 **rchip)
1da177e4 2159{
95de7766 2160 struct snd_azf3328 *chip;
1da177e4 2161 int err;
95de7766 2162 static struct snd_device_ops ops = {
1da177e4
LT
2163 .dev_free = snd_azf3328_dev_free,
2164 };
dfbf9511
AM
2165 u8 dma_init;
2166 enum snd_azf3328_codec_type codec_type;
1da177e4
LT
2167
2168 *rchip = NULL;
2169
02330fba
AM
2170 err = pci_enable_device(pci);
2171 if (err < 0)
1da177e4
LT
2172 return err;
2173
e560d8d8 2174 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1da177e4 2175 if (chip == NULL) {
d91c64c8
AM
2176 err = -ENOMEM;
2177 goto out_err;
1da177e4
LT
2178 }
2179 spin_lock_init(&chip->reg_lock);
2180 chip->card = card;
2181 chip->pci = pci;
2182 chip->irq = -1;
2183
2184 /* check if we can restrict PCI DMA transfers to 24 bits */
2f4f27d4
YH
2185 if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 ||
2186 pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) {
02330fba
AM
2187 snd_printk(KERN_ERR "architecture does not support "
2188 "24bit PCI busmaster DMA\n"
2189 );
d91c64c8
AM
2190 err = -ENXIO;
2191 goto out_err;
1da177e4
LT
2192 }
2193
02330fba
AM
2194 err = pci_request_regions(pci, "Aztech AZF3328");
2195 if (err < 0)
d91c64c8 2196 goto out_err;
1da177e4 2197
dfbf9511 2198 chip->ctrl_io = pci_resource_start(pci, 0);
02330fba
AM
2199 chip->game_io = pci_resource_start(pci, 1);
2200 chip->mpu_io = pci_resource_start(pci, 2);
dfbf9511 2201 chip->opl3_io = pci_resource_start(pci, 3);
02330fba
AM
2202 chip->mixer_io = pci_resource_start(pci, 4);
2203
dfbf9511
AM
2204 chip->codecs[AZF_CODEC_PLAYBACK].io_base =
2205 chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK;
2206 chip->codecs[AZF_CODEC_PLAYBACK].name = "PLAYBACK";
2207 chip->codecs[AZF_CODEC_CAPTURE].io_base =
2208 chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE;
2209 chip->codecs[AZF_CODEC_CAPTURE].name = "CAPTURE";
2210 chip->codecs[AZF_CODEC_I2S_OUT].io_base =
2211 chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT;
2212 chip->codecs[AZF_CODEC_I2S_OUT].name = "I2S_OUT";
1da177e4 2213
437a5a46
TI
2214 if (request_irq(pci->irq, snd_azf3328_interrupt,
2215 IRQF_SHARED, card->shortname, chip)) {
99b359ba 2216 snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
d91c64c8
AM
2217 err = -EBUSY;
2218 goto out_err;
1da177e4
LT
2219 }
2220 chip->irq = pci->irq;
2221 pci_set_master(pci);
2222 synchronize_irq(chip->irq);
2223
d91c64c8 2224 snd_azf3328_debug_show_ports(chip);
02330fba
AM
2225
2226 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
2227 if (err < 0)
d91c64c8 2228 goto out_err;
1da177e4
LT
2229
2230 /* create mixer interface & switches */
02330fba
AM
2231 err = snd_azf3328_mixer_new(chip);
2232 if (err < 0)
d91c64c8 2233 goto out_err;
1da177e4 2234
dfbf9511
AM
2235 /* standard codec init stuff */
2236 /* default DMA init value */
2237 dma_init = DMA_RUN_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE;
2238
2239 for (codec_type = AZF_CODEC_PLAYBACK;
2240 codec_type <= AZF_CODEC_I2S_OUT; ++codec_type) {
2241 struct snd_azf3328_codec_data *codec =
2242 &chip->codecs[codec_type];
1da177e4 2243
dfbf9511
AM
2244 /* shutdown codecs to save power */
2245 /* have ...ctrl_codec_activity() act properly */
2246 codec->running = 1;
2247 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
1da177e4 2248
dfbf9511
AM
2249 spin_lock_irq(&chip->reg_lock);
2250 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS,
2251 dma_init);
2252 spin_unlock_irq(&chip->reg_lock);
2253 }
1da177e4
LT
2254
2255 snd_card_set_dev(card, &pci->dev);
2256
2257 *rchip = chip;
d91c64c8
AM
2258
2259 err = 0;
2260 goto out;
2261
2262out_err:
2263 if (chip)
2264 snd_azf3328_free(chip);
2265 pci_disable_device(pci);
2266
2267out:
2268 return err;
1da177e4
LT
2269}
2270
d91c64c8
AM
2271static int __devinit
2272snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
1da177e4
LT
2273{
2274 static int dev;
95de7766
TI
2275 struct snd_card *card;
2276 struct snd_azf3328 *chip;
2277 struct snd_opl3 *opl3;
1da177e4
LT
2278 int err;
2279
2280 snd_azf3328_dbgcallenter();
2281 if (dev >= SNDRV_CARDS)
2282 return -ENODEV;
2283 if (!enable[dev]) {
2284 dev++;
2285 return -ENOENT;
2286 }
2287
e58de7ba
TI
2288 err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
2289 if (err < 0)
2290 return err;
1da177e4
LT
2291
2292 strcpy(card->driver, "AZF3328");
2293 strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
2294
02330fba
AM
2295 err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip);
2296 if (err < 0)
d91c64c8 2297 goto out_err;
1da177e4 2298
ca54bde3
AM
2299 card->private_data = chip;
2300
02330fba
AM
2301 err = snd_mpu401_uart_new(
2302 card, 0, MPU401_HW_MPU401, chip->mpu_io, MPU401_INFO_INTEGRATED,
2303 pci->irq, 0, &chip->rmidi
2304 );
2305 if (err < 0) {
2306 snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n",
2307 chip->mpu_io
2308 );
d91c64c8
AM
2309 goto out_err;
2310 }
2311
02330fba
AM
2312 err = snd_azf3328_timer(chip, 0);
2313 if (err < 0)
d91c64c8 2314 goto out_err;
1da177e4 2315
dfbf9511 2316 err = snd_azf3328_pcm(chip);
02330fba 2317 if (err < 0)
d91c64c8 2318 goto out_err;
1da177e4 2319
02330fba 2320 if (snd_opl3_create(card, chip->opl3_io, chip->opl3_io+2,
1da177e4 2321 OPL3_HW_AUTO, 1, &opl3) < 0) {
99b359ba 2322 snd_printk(KERN_ERR "azf3328: no OPL3 device at 0x%lx-0x%lx?\n",
02330fba
AM
2323 chip->opl3_io, chip->opl3_io+2
2324 );
1da177e4 2325 } else {
02330fba
AM
2326 /* need to use IDs 1, 2 since ID 0 is snd_azf3328_timer above */
2327 err = snd_opl3_timer_new(opl3, 1, 2);
2328 if (err < 0)
2329 goto out_err;
2330 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
2331 if (err < 0)
d91c64c8 2332 goto out_err;
1da177e4
LT
2333 }
2334
ca54bde3
AM
2335 opl3->private_data = chip;
2336
1da177e4 2337 sprintf(card->longname, "%s at 0x%lx, irq %i",
dfbf9511 2338 card->shortname, chip->ctrl_io, chip->irq);
1da177e4 2339
02330fba
AM
2340 err = snd_card_register(card);
2341 if (err < 0)
d91c64c8 2342 goto out_err;
1da177e4
LT
2343
2344#ifdef MODULE
2345 printk(
e24a121a
AM
2346"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n"
2347"azt3328: Hardware was completely undocumented, unfortunately.\n"
d91c64c8
AM
2348"azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n"
2349"azt3328: User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n",
2350 1024000 / seqtimer_scaling, seqtimer_scaling);
1da177e4
LT
2351#endif
2352
02330fba 2353 snd_azf3328_gameport(chip, dev);
1da177e4
LT
2354
2355 pci_set_drvdata(pci, card);
2356 dev++;
2357
d91c64c8
AM
2358 err = 0;
2359 goto out;
02330fba 2360
d91c64c8 2361out_err:
02330fba 2362 snd_printk(KERN_ERR "azf3328: something failed, exiting\n");
d91c64c8 2363 snd_card_free(card);
02330fba 2364
d91c64c8 2365out:
1da177e4 2366 snd_azf3328_dbgcallleave();
d91c64c8 2367 return err;
1da177e4
LT
2368}
2369
d91c64c8
AM
2370static void __devexit
2371snd_azf3328_remove(struct pci_dev *pci)
1da177e4
LT
2372{
2373 snd_azf3328_dbgcallenter();
2374 snd_card_free(pci_get_drvdata(pci));
2375 pci_set_drvdata(pci, NULL);
2376 snd_azf3328_dbgcallleave();
2377}
2378
ca54bde3
AM
2379#ifdef CONFIG_PM
2380static int
2381snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
2382{
2383 struct snd_card *card = pci_get_drvdata(pci);
2384 struct snd_azf3328 *chip = card->private_data;
02330fba 2385 unsigned reg;
ca54bde3
AM
2386
2387 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
02330fba 2388
dfbf9511
AM
2389 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);
2390 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);
ca54bde3 2391
02330fba
AM
2392 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
2393 chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2);
ca54bde3
AM
2394
2395 /* make sure to disable master volume etc. to prevent looping sound */
2396 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
2397 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
02330fba 2398
dfbf9511
AM
2399 for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg)
2400 chip->saved_regs_ctrl[reg] = inw(chip->ctrl_io + reg * 2);
627d3e7a
AM
2401
2402 /* manually store the one currently relevant write-only reg, too */
dfbf9511 2403 chip->saved_regs_ctrl[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH;
627d3e7a 2404
02330fba
AM
2405 for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg)
2406 chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2);
2407 for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg)
2408 chip->saved_regs_mpu[reg] = inw(chip->mpu_io + reg * 2);
2409 for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg)
2410 chip->saved_regs_opl3[reg] = inw(chip->opl3_io + reg * 2);
ca54bde3 2411
ca54bde3
AM
2412 pci_disable_device(pci);
2413 pci_save_state(pci);
30b35399 2414 pci_set_power_state(pci, pci_choose_state(pci, state));
ca54bde3
AM
2415 return 0;
2416}
2417
2418static int
2419snd_azf3328_resume(struct pci_dev *pci)
2420{
2421 struct snd_card *card = pci_get_drvdata(pci);
dfbf9511 2422 const struct snd_azf3328 *chip = card->private_data;
02330fba 2423 unsigned reg;
ca54bde3 2424
ca54bde3 2425 pci_set_power_state(pci, PCI_D0);
30b35399
TI
2426 pci_restore_state(pci);
2427 if (pci_enable_device(pci) < 0) {
2428 printk(KERN_ERR "azt3328: pci_enable_device failed, "
2429 "disabling device\n");
2430 snd_card_disconnect(card);
2431 return -EIO;
2432 }
ca54bde3
AM
2433 pci_set_master(pci);
2434
02330fba
AM
2435 for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg)
2436 outw(chip->saved_regs_game[reg], chip->game_io + reg * 2);
2437 for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg)
2438 outw(chip->saved_regs_mpu[reg], chip->mpu_io + reg * 2);
2439 for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg)
2440 outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2);
2441 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
2442 outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2);
dfbf9511
AM
2443 for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg)
2444 outw(chip->saved_regs_ctrl[reg], chip->ctrl_io + reg * 2);
ca54bde3
AM
2445
2446 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
2447 return 0;
2448}
02330fba 2449#endif /* CONFIG_PM */
ca54bde3
AM
2450
2451
1da177e4
LT
2452static struct pci_driver driver = {
2453 .name = "AZF3328",
2454 .id_table = snd_azf3328_ids,
2455 .probe = snd_azf3328_probe,
2456 .remove = __devexit_p(snd_azf3328_remove),
ca54bde3
AM
2457#ifdef CONFIG_PM
2458 .suspend = snd_azf3328_suspend,
2459 .resume = snd_azf3328_resume,
2460#endif
1da177e4
LT
2461};
2462
d91c64c8
AM
2463static int __init
2464alsa_card_azf3328_init(void)
1da177e4
LT
2465{
2466 int err;
2467 snd_azf3328_dbgcallenter();
01d25d46 2468 err = pci_register_driver(&driver);
1da177e4
LT
2469 snd_azf3328_dbgcallleave();
2470 return err;
2471}
2472
d91c64c8
AM
2473static void __exit
2474alsa_card_azf3328_exit(void)
1da177e4
LT
2475{
2476 snd_azf3328_dbgcallenter();
2477 pci_unregister_driver(&driver);
2478 snd_azf3328_dbgcallleave();
2479}
2480
2481module_init(alsa_card_azf3328_init)
2482module_exit(alsa_card_azf3328_exit)
This page took 0.608464 seconds and 5 git commands to generate.