aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/azt3328.c
diff options
context:
space:
mode:
authorAndreas Mohr <andi@lisas.de>2009-07-05 07:55:46 -0400
committerTakashi Iwai <tiwai@suse.de>2009-07-06 02:24:47 -0400
commitdfbf9511155d3584b8747c935216077f46eb9a4f (patch)
tree0591d571c38dd032eff9c2ca41ab1c34e19aa4f8 /sound/pci/azt3328.c
parent3eff8958308ed875a4e845d59a498288f8bbad77 (diff)
ALSA: azt3328: large codec cleanup, add I2S port etc.
- fully separate codec I/O port handling, enabling the use of a single function each for all codecs (playback, capture, I2S out) - add a new separate pcm for I2S out port (UNTESTED, no I2S DAC available yet) - switch gameport to low frequency while idle, to try to reduce noise/power - improve snd_azf3328_codec_setdmaa() calculation - minor variable type cleanup (u16, bool etc.) - add some doc updates (help those lost Windows users, debug help, ...) Note that due to the large cleanup aspect of the codec I/O change, I was able to fit everything including all improvements into the same binary size!! (a measly 10 bytes more or so) This should now be the almost last patch to this driver (minus some possible kernel clocksource patch and x86_64 fixes or so). I just felt like taking a break from the usual stuff and wanted to get this driver's structure finished, and it's rather clean now... Tested, working and checkpatch.pl:ed on 2.6.30-rc5, applies cleanly to 2.6.30 proper. Signed-off-by: Andreas Mohr <andi@lisas.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/azt3328.c')
-rw-r--r--sound/pci/azt3328.c978
1 files changed, 524 insertions, 454 deletions
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index f290bc56178f..39dfdaa6a56f 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, 2005 - 2008 by Andreas Mohr <andi AT lisas.de> 3 * Copyright (C) 2002, 2005 - 2009 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),
@@ -10,6 +10,13 @@
10 * PCI168 A/AP, sub ID 8000 10 * PCI168 A/AP, sub ID 8000
11 * Please give me feedback in case you try my driver with one of these!! 11 * Please give me feedback in case you try my driver with one of these!!
12 * 12 *
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 *
13 * GPL LICENSE 20 * GPL LICENSE
14 * This program is free software; you can redistribute it and/or modify 21 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by 22 * it under the terms of the GNU General Public License as published by
@@ -71,10 +78,11 @@
71 * - built-in General DirectX timer having a 20 bits counter 78 * - built-in General DirectX timer having a 20 bits counter
72 * with 1us resolution (see below!) 79 * with 1us resolution (see below!)
73 * - I2S serial output port for external DAC 80 * - I2S serial output port for external DAC
81 * [FIXME: 3.3V or 5V level? maximum rate is 66.2kHz right?]
74 * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI 82 * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI
75 * - supports hardware volume control 83 * - supports hardware volume control
76 * - single chip low cost solution (128 pin QFP) 84 * - single chip low cost solution (128 pin QFP)
77 * - supports programmable Sub-vendor and Sub-system ID 85 * - supports programmable Sub-vendor and Sub-system ID [24C02 SEEPROM chip]
78 * required for Microsoft's logo compliance (FIXME: where?) 86 * required for Microsoft's logo compliance (FIXME: where?)
79 * At least the Trident 4D Wave DX has one bit somewhere 87 * At least the Trident 4D Wave DX has one bit somewhere
80 * to enable writes to PCI subsystem VID registers, that should be it. 88 * to enable writes to PCI subsystem VID registers, that should be it.
@@ -82,6 +90,7 @@
82 * some custom data starting at 0x80. What kind of config settings 90 * some custom data starting at 0x80. What kind of config settings
83 * are located in our extended PCI space anyway?? 91 * are located in our extended PCI space anyway??
84 * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms 92 * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms
93 * [TDA1517P chip]
85 * 94 *
86 * Note that this driver now is actually *better* than the Windows driver, 95 * Note that this driver now is actually *better* than the Windows driver,
87 * since it additionally supports the card's 1MHz DirectX timer - just try 96 * since it additionally supports the card's 1MHz DirectX timer - just try
@@ -146,10 +155,15 @@
146 * to read the Digital Enhanced Game Port. Not sure whether it is fixable. 155 * to read the Digital Enhanced Game Port. Not sure whether it is fixable.
147 * 156 *
148 * TODO 157 * TODO
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
149 * - test MPU401 MIDI playback etc. 162 * - test MPU401 MIDI playback etc.
150 * - add more power micro-management (disable various units of the card 163 * - add more power micro-management (disable various units of the card
151 * as long as they're unused). However this requires more I/O ports which I 164 * as long as they're unused, to improve audio quality and save power).
152 * haven't figured out yet and which thus might not even exist... 165 * However this requires more I/O ports which I haven't figured out yet
166 * and which thus might not even exist...
153 * The standard suspend/resume functionality could probably make use of 167 * The standard suspend/resume functionality could probably make use of
154 * some improvement, too... 168 * some improvement, too...
155 * - figure out what all unknown port bits are responsible for 169 * - figure out what all unknown port bits are responsible for
@@ -185,6 +199,26 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
185#define SUPPORT_GAMEPORT 1 199#define SUPPORT_GAMEPORT 1
186#endif 200#endif
187 201
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
188#define DEBUG_MISC 0 222#define DEBUG_MISC 0
189#define DEBUG_CALLS 0 223#define DEBUG_CALLS 0
190#define DEBUG_MIXER 0 224#define DEBUG_MIXER 0
@@ -250,22 +284,23 @@ static int seqtimer_scaling = 128;
250module_param(seqtimer_scaling, int, 0444); 284module_param(seqtimer_scaling, int, 0444);
251MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); 285MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");
252 286
253struct snd_azf3328_audio_stream { 287struct snd_azf3328_codec_data {
288 unsigned long io_base;
254 struct snd_pcm_substream *substream; 289 struct snd_pcm_substream *substream;
255 int enabled; 290 bool running;
256 int running; 291 const char *name;
257 unsigned long portbase;
258}; 292};
259 293
260enum snd_azf3328_stream_index { 294enum snd_azf3328_codec_type {
261 AZF_PLAYBACK = 0, 295 AZF_CODEC_PLAYBACK = 0,
262 AZF_CAPTURE = 1, 296 AZF_CODEC_CAPTURE = 1,
297 AZF_CODEC_I2S_OUT = 2,
263}; 298};
264 299
265struct snd_azf3328 { 300struct snd_azf3328 {
266 /* often-used fields towards beginning, then grouped */ 301 /* often-used fields towards beginning, then grouped */
267 302
268 unsigned long codec_io; /* usually 0xb000, size 128 */ 303 unsigned long ctrl_io; /* usually 0xb000, size 128 */
269 unsigned long game_io; /* usually 0xb400, size 8 */ 304 unsigned long game_io; /* usually 0xb400, size 8 */
270 unsigned long mpu_io; /* usually 0xb800, size 4 */ 305 unsigned long mpu_io; /* usually 0xb800, size 4 */
271 unsigned long opl3_io; /* usually 0xbc00, size 8 */ 306 unsigned long opl3_io; /* usually 0xbc00, size 8 */
@@ -275,15 +310,17 @@ struct snd_azf3328 {
275 310
276 struct snd_timer *timer; 311 struct snd_timer *timer;
277 312
278 struct snd_pcm *pcm; 313 struct snd_pcm *pcm[3];
279 struct snd_azf3328_audio_stream audio_stream[2]; 314
315 /* playback, recording and I2S out codecs */
316 struct snd_azf3328_codec_data codecs[3];
280 317
281 struct snd_card *card; 318 struct snd_card *card;
282 struct snd_rawmidi *rmidi; 319 struct snd_rawmidi *rmidi;
283 320
284#ifdef SUPPORT_GAMEPORT 321#ifdef SUPPORT_GAMEPORT
285 struct gameport *gameport; 322 struct gameport *gameport;
286 int axes[4]; 323 u16 axes[4];
287#endif 324#endif
288 325
289 struct pci_dev *pci; 326 struct pci_dev *pci;
@@ -293,12 +330,12 @@ struct snd_azf3328 {
293 * If we need to add more registers here, then we might try to fold this 330 * If we need to add more registers here, then we might try to fold this
294 * into some transparent combined shadow register handling with 331 * into some transparent combined shadow register handling with
295 * CONFIG_PM register storage below, but that's slightly difficult. */ 332 * CONFIG_PM register storage below, but that's slightly difficult. */
296 u16 shadow_reg_codec_6AH; 333 u16 shadow_reg_ctrl_6AH;
297 334
298#ifdef CONFIG_PM 335#ifdef CONFIG_PM
299 /* register value containers for power management 336 /* register value containers for power management
300 * Note: not always full I/O range preserved (just like Win driver!) */ 337 * Note: not always full I/O range preserved (just like Win driver!) */
301 u16 saved_regs_codec[AZF_IO_SIZE_CODEC_PM / 2]; 338 u16 saved_regs_ctrl[AZF_IO_SIZE_CTRL_PM / 2];
302 u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2]; 339 u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2];
303 u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2]; 340 u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2];
304 u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2]; 341 u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2];
@@ -316,7 +353,7 @@ MODULE_DEVICE_TABLE(pci, snd_azf3328_ids);
316 353
317 354
318static int 355static int
319snd_azf3328_io_reg_setb(unsigned reg, u8 mask, int do_set) 356snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set)
320{ 357{
321 u8 prev = inb(reg), new; 358 u8 prev = inb(reg), new;
322 359
@@ -331,39 +368,72 @@ snd_azf3328_io_reg_setb(unsigned reg, u8 mask, int do_set)
331} 368}
332 369
333static inline void 370static inline void
334snd_azf3328_codec_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value) 371snd_azf3328_codec_outb(const struct snd_azf3328_codec_data *codec,
372 unsigned reg,
373 u8 value
374)
335{ 375{
336 outb(value, chip->codec_io + reg); 376 outb(value, codec->io_base + reg);
337} 377}
338 378
339static inline u8 379static inline u8
340snd_azf3328_codec_inb(const struct snd_azf3328 *chip, unsigned reg) 380snd_azf3328_codec_inb(const struct snd_azf3328_codec_data *codec, unsigned reg)
341{ 381{
342 return inb(chip->codec_io + reg); 382 return inb(codec->io_base + reg);
343} 383}
344 384
345static inline void 385static inline void
346snd_azf3328_codec_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) 386snd_azf3328_codec_outw(const struct snd_azf3328_codec_data *codec,
387 unsigned reg,
388 u16 value
389)
347{ 390{
348 outw(value, chip->codec_io + reg); 391 outw(value, codec->io_base + reg);
349} 392}
350 393
351static inline u16 394static inline u16
352snd_azf3328_codec_inw(const struct snd_azf3328 *chip, unsigned reg) 395snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg)
353{ 396{
354 return inw(chip->codec_io + reg); 397 return inw(codec->io_base + reg);
355} 398}
356 399
357static inline void 400static inline void
358snd_azf3328_codec_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value) 401snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec,
402 unsigned reg,
403 u32 value
404)
359{ 405{
360 outl(value, chip->codec_io + reg); 406 outl(value, codec->io_base + reg);
361} 407}
362 408
363static inline u32 409static inline u32
364snd_azf3328_codec_inl(const struct snd_azf3328 *chip, unsigned reg) 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)
365{ 417{
366 return inl(chip->codec_io + reg); 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);
367} 437}
368 438
369static inline void 439static inline void
@@ -404,13 +474,13 @@ snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg)
404 474
405#define AZF_MUTE_BIT 0x80 475#define AZF_MUTE_BIT 0x80
406 476
407static int 477static bool
408snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip, 478snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
409 unsigned reg, int do_mute 479 unsigned reg, bool do_mute
410) 480)
411{ 481{
412 unsigned long portbase = chip->mixer_io + reg + 1; 482 unsigned long portbase = chip->mixer_io + reg + 1;
413 int updated; 483 bool updated;
414 484
415 /* the mute bit is on the *second* (i.e. right) register of a 485 /* the mute bit is on the *second* (i.e. right) register of a
416 * left/right channel setting */ 486 * left/right channel setting */
@@ -569,7 +639,7 @@ snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol,
569{ 639{
570 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); 640 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
571 struct azf3328_mixer_reg reg; 641 struct azf3328_mixer_reg reg;
572 unsigned int oreg, val; 642 u16 oreg, val;
573 643
574 snd_azf3328_dbgcallenter(); 644 snd_azf3328_dbgcallenter();
575 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 645 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -600,7 +670,7 @@ snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol,
600{ 670{
601 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); 671 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
602 struct azf3328_mixer_reg reg; 672 struct azf3328_mixer_reg reg;
603 unsigned int oreg, nreg, val; 673 u16 oreg, nreg, val;
604 674
605 snd_azf3328_dbgcallenter(); 675 snd_azf3328_dbgcallenter();
606 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 676 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -709,7 +779,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
709{ 779{
710 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); 780 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
711 struct azf3328_mixer_reg reg; 781 struct azf3328_mixer_reg reg;
712 unsigned int oreg, nreg, val; 782 u16 oreg, nreg, val;
713 783
714 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 784 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
715 oreg = snd_azf3328_mixer_inw(chip, reg.reg); 785 oreg = snd_azf3328_mixer_inw(chip, reg.reg);
@@ -867,14 +937,15 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream)
867 937
868static void 938static void
869snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, 939snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
870 unsigned reg, 940 enum snd_azf3328_codec_type codec_type,
871 enum azf_freq_t bitrate, 941 enum azf_freq_t bitrate,
872 unsigned int format_width, 942 unsigned int format_width,
873 unsigned int channels 943 unsigned int channels
874) 944)
875{ 945{
876 u16 val = 0xff00;
877 unsigned long flags; 946 unsigned long flags;
947 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
948 u16 val = 0xff00;
878 949
879 snd_azf3328_dbgcallenter(); 950 snd_azf3328_dbgcallenter();
880 switch (bitrate) { 951 switch (bitrate) {
@@ -917,7 +988,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
917 spin_lock_irqsave(&chip->reg_lock, flags); 988 spin_lock_irqsave(&chip->reg_lock, flags);
918 989
919 /* set bitrate/format */ 990 /* set bitrate/format */
920 snd_azf3328_codec_outw(chip, reg, val); 991 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val);
921 992
922 /* changing the bitrate/format settings switches off the 993 /* changing the bitrate/format settings switches off the
923 * audio output with an annoying click in case of 8/16bit format change 994 * audio output with an annoying click in case of 8/16bit format change
@@ -926,11 +997,11 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
926 * (FIXME: yes, it works, but what exactly am I doing here?? :) 997 * (FIXME: yes, it works, but what exactly am I doing here?? :)
927 * FIXME: does this have some side effects for full-duplex 998 * FIXME: does this have some side effects for full-duplex
928 * or other dramatic side effects? */ 999 * or other dramatic side effects? */
929 if (reg == IDX_IO_PLAY_SOUNDFORMAT) /* only do it for playback */ 1000 if (codec_type == AZF_CODEC_PLAYBACK) /* only do it for playback */
930 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1001 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
931 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | 1002 snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) |
932 DMA_PLAY_SOMETHING1 | 1003 DMA_RUN_SOMETHING1 |
933 DMA_PLAY_SOMETHING2 | 1004 DMA_RUN_SOMETHING2 |
934 SOMETHING_ALMOST_ALWAYS_SET | 1005 SOMETHING_ALMOST_ALWAYS_SET |
935 DMA_EPILOGUE_SOMETHING | 1006 DMA_EPILOGUE_SOMETHING |
936 DMA_SOMETHING_ELSE 1007 DMA_SOMETHING_ELSE
@@ -942,134 +1013,132 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
942 1013
943static inline void 1014static inline void
944snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip, 1015snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip,
945 unsigned reg 1016 enum snd_azf3328_codec_type codec_type
946) 1017)
947{ 1018{
948 /* choose lowest frequency for low power consumption. 1019 /* choose lowest frequency for low power consumption.
949 * While this will cause louder noise due to rather coarse frequency, 1020 * While this will cause louder noise due to rather coarse frequency,
950 * it should never matter since output should always 1021 * it should never matter since output should always
951 * get disabled properly when idle anyway. */ 1022 * get disabled properly when idle anyway. */
952 snd_azf3328_codec_setfmt(chip, reg, AZF_FREQ_4000, 8, 1); 1023 snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1);
953} 1024}
954 1025
955static void 1026static void
956snd_azf3328_codec_reg_6AH_update(struct snd_azf3328 *chip, 1027snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip,
957 unsigned bitmask, 1028 unsigned bitmask,
958 int enable 1029 bool enable
959) 1030)
960{ 1031{
961 if (enable) 1032 if (enable)
962 chip->shadow_reg_codec_6AH &= ~bitmask; 1033 chip->shadow_reg_ctrl_6AH &= ~bitmask;
963 else 1034 else
964 chip->shadow_reg_codec_6AH |= bitmask; 1035 chip->shadow_reg_ctrl_6AH |= bitmask;
965 snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n", 1036 snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n",
966 bitmask, enable, chip->shadow_reg_codec_6AH); 1037 bitmask, enable, chip->shadow_reg_ctrl_6AH);
967 snd_azf3328_codec_outw(chip, IDX_IO_6AH, chip->shadow_reg_codec_6AH); 1038 snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH);
968} 1039}
969 1040
970static inline void 1041static inline void
971snd_azf3328_codec_enable(struct snd_azf3328 *chip, int enable) 1042snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable)
972{ 1043{
973 snd_azf3328_dbgplay("codec_enable %d\n", enable); 1044 snd_azf3328_dbgplay("codec_enable %d\n", enable);
974 /* no idea what exactly is being done here, but I strongly assume it's 1045 /* no idea what exactly is being done here, but I strongly assume it's
975 * PM related */ 1046 * PM related */
976 snd_azf3328_codec_reg_6AH_update( 1047 snd_azf3328_ctrl_reg_6AH_update(
977 chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable 1048 chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable
978 ); 1049 );
979} 1050}
980 1051
981static void 1052static void
982snd_azf3328_codec_activity(struct snd_azf3328 *chip, 1053snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip,
983 enum snd_azf3328_stream_index stream_type, 1054 enum snd_azf3328_codec_type codec_type,
984 int enable 1055 bool enable
985) 1056)
986{ 1057{
987 int need_change = (chip->audio_stream[stream_type].running != enable); 1058 struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1059 bool need_change = (codec->running != enable);
988 1060
989 snd_azf3328_dbgplay( 1061 snd_azf3328_dbgplay(
990 "codec_activity: type %d, enable %d, need_change %d\n", 1062 "codec_activity: %s codec, enable %d, need_change %d\n",
991 stream_type, enable, need_change 1063 codec->name, enable, need_change
992 ); 1064 );
993 if (need_change) { 1065 if (need_change) {
994 enum snd_azf3328_stream_index other = 1066 static const struct {
995 (stream_type == AZF_PLAYBACK) ? 1067 enum snd_azf3328_codec_type other1;
996 AZF_CAPTURE : AZF_PLAYBACK; 1068 enum snd_azf3328_codec_type other2;
997 /* small check to prevent shutting down the other party 1069 } peer_codecs[3] =
998 * in case it's active */ 1070 { { AZF_CODEC_CAPTURE, AZF_CODEC_I2S_OUT },
999 if ((enable) || !(chip->audio_stream[other].running)) 1071 { AZF_CODEC_PLAYBACK, AZF_CODEC_I2S_OUT },
1000 snd_azf3328_codec_enable(chip, enable); 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);
1001 1092
1002 /* ...and adjust clock, too 1093 /* ...and adjust clock, too
1003 * (reduce noise and power consumption) */ 1094 * (reduce noise and power consumption) */
1004 if (!enable) 1095 if (!enable)
1005 snd_azf3328_codec_setfmt_lowpower( 1096 snd_azf3328_codec_setfmt_lowpower(
1006 chip, 1097 chip,
1007 chip->audio_stream[stream_type].portbase 1098 codec_type
1008 + IDX_IO_PLAY_SOUNDFORMAT
1009 ); 1099 );
1010 } 1100 }
1011 chip->audio_stream[stream_type].running = enable; 1101 codec->running = enable;
1012} 1102}
1013 1103
1014static void 1104static void
1015snd_azf3328_setdmaa(struct snd_azf3328 *chip, 1105snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
1016 long unsigned int addr, 1106 enum snd_azf3328_codec_type codec_type,
1017 unsigned int count, 1107 unsigned long addr,
1018 unsigned int size, 1108 unsigned int count,
1019 enum snd_azf3328_stream_index stream_type 1109 unsigned int size
1020) 1110)
1021{ 1111{
1112 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1022 snd_azf3328_dbgcallenter(); 1113 snd_azf3328_dbgcallenter();
1023 if (!chip->audio_stream[stream_type].running) { 1114 if (!codec->running) {
1024 /* AZF3328 uses a two buffer pointer DMA playback approach */ 1115 /* AZF3328 uses a two buffer pointer DMA transfer approach */
1025 1116
1026 unsigned long flags, portbase, addr_area2; 1117 unsigned long flags;
1027 1118
1028 /* width 32bit (prevent overflow): */ 1119 /* width 32bit (prevent overflow): */
1029 unsigned long count_areas, count_tmp; 1120 u32 addr_area2, count_areas, lengths;
1030 1121
1031 portbase = chip->audio_stream[stream_type].portbase;
1032 count_areas = size/2; 1122 count_areas = size/2;
1033 addr_area2 = addr+count_areas; 1123 addr_area2 = addr+count_areas;
1034 count_areas--; /* max. index */ 1124 count_areas--; /* max. index */
1035 snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas); 1125 snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas);
1036 1126
1037 /* build combined I/O buffer length word */ 1127 /* build combined I/O buffer length word */
1038 count_tmp = count_areas; 1128 lengths = (count_areas << 16) | (count_areas);
1039 count_areas |= (count_tmp << 16);
1040 spin_lock_irqsave(&chip->reg_lock, flags); 1129 spin_lock_irqsave(&chip->reg_lock, flags);
1041 outl(addr, portbase + IDX_IO_PLAY_DMA_START_1); 1130 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr);
1042 outl(addr_area2, portbase + IDX_IO_PLAY_DMA_START_2); 1131 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2,
1043 outl(count_areas, portbase + IDX_IO_PLAY_DMA_LEN_1); 1132 addr_area2);
1133 snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS,
1134 lengths);
1044 spin_unlock_irqrestore(&chip->reg_lock, flags); 1135 spin_unlock_irqrestore(&chip->reg_lock, flags);
1045 } 1136 }
1046 snd_azf3328_dbgcallleave(); 1137 snd_azf3328_dbgcallleave();
1047} 1138}
1048 1139
1049static int 1140static int
1050snd_azf3328_playback_prepare(struct snd_pcm_substream *substream) 1141snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)
1051{
1052#if 0
1053 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1054 struct snd_pcm_runtime *runtime = substream->runtime;
1055 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1056 unsigned int count = snd_pcm_lib_period_bytes(substream);
1057#endif
1058
1059 snd_azf3328_dbgcallenter();
1060#if 0
1061 snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,
1062 runtime->rate,
1063 snd_pcm_format_width(runtime->format),
1064 runtime->channels);
1065 snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_PLAYBACK);
1066#endif
1067 snd_azf3328_dbgcallleave();
1068 return 0;
1069}
1070
1071static int
1072snd_azf3328_capture_prepare(struct snd_pcm_substream *substream)
1073{ 1142{
1074#if 0 1143#if 0
1075 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1144 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
@@ -1080,135 +1149,161 @@ snd_azf3328_capture_prepare(struct snd_pcm_substream *substream)
1080 1149
1081 snd_azf3328_dbgcallenter(); 1150 snd_azf3328_dbgcallenter();
1082#if 0 1151#if 0
1083 snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, 1152 snd_azf3328_codec_setfmt(chip, AZF_CODEC_...,
1084 runtime->rate, 1153 runtime->rate,
1085 snd_pcm_format_width(runtime->format), 1154 snd_pcm_format_width(runtime->format),
1086 runtime->channels); 1155 runtime->channels);
1087 snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_CAPTURE); 1156 snd_azf3328_codec_setdmaa(chip, AZF_CODEC_...,
1157 runtime->dma_addr, count, size);
1088#endif 1158#endif
1089 snd_azf3328_dbgcallleave(); 1159 snd_azf3328_dbgcallleave();
1090 return 0; 1160 return 0;
1091} 1161}
1092 1162
1093static int 1163static int
1094snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) 1164snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
1165 struct snd_pcm_substream *substream, int cmd)
1095{ 1166{
1096 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1167 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1168 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1097 struct snd_pcm_runtime *runtime = substream->runtime; 1169 struct snd_pcm_runtime *runtime = substream->runtime;
1098 int result = 0; 1170 int result = 0;
1099 unsigned int status1; 1171 u16 flags1;
1100 int previously_muted; 1172 bool previously_muted = 0;
1173 bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type);
1101 1174
1102 snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd); 1175 snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd);
1103 1176
1104 switch (cmd) { 1177 switch (cmd) {
1105 case SNDRV_PCM_TRIGGER_START: 1178 case SNDRV_PCM_TRIGGER_START:
1106 snd_azf3328_dbgplay("START PLAYBACK\n"); 1179 snd_azf3328_dbgplay("START %s\n", codec->name);
1107 1180
1108 /* mute WaveOut (avoid clicking during setup) */ 1181 if (is_playback_codec) {
1109 previously_muted = 1182 /* mute WaveOut (avoid clicking during setup) */
1110 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 1183 previously_muted =
1184 snd_azf3328_mixer_set_mute(
1185 chip, IDX_MIXER_WAVEOUT, 1
1186 );
1187 }
1111 1188
1112 snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, 1189 snd_azf3328_codec_setfmt(chip, codec_type,
1113 runtime->rate, 1190 runtime->rate,
1114 snd_pcm_format_width(runtime->format), 1191 snd_pcm_format_width(runtime->format),
1115 runtime->channels); 1192 runtime->channels);
1116 1193
1117 spin_lock(&chip->reg_lock); 1194 spin_lock(&chip->reg_lock);
1118 /* first, remember current value: */ 1195 /* first, remember current value: */
1119 status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); 1196 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
1120 1197
1121 /* stop playback */ 1198 /* stop transfer */
1122 status1 &= ~DMA_RESUME; 1199 flags1 &= ~DMA_RESUME;
1123 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1200 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1124 1201
1125 /* FIXME: clear interrupts or what??? */ 1202 /* FIXME: clear interrupts or what??? */
1126 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff); 1203 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff);
1127 spin_unlock(&chip->reg_lock); 1204 spin_unlock(&chip->reg_lock);
1128 1205
1129 snd_azf3328_setdmaa(chip, runtime->dma_addr, 1206 snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr,
1130 snd_pcm_lib_period_bytes(substream), 1207 snd_pcm_lib_period_bytes(substream),
1131 snd_pcm_lib_buffer_bytes(substream), 1208 snd_pcm_lib_buffer_bytes(substream)
1132 AZF_PLAYBACK); 1209 );
1133 1210
1134 spin_lock(&chip->reg_lock); 1211 spin_lock(&chip->reg_lock);
1135#ifdef WIN9X 1212#ifdef WIN9X
1136 /* FIXME: enable playback/recording??? */ 1213 /* FIXME: enable playback/recording??? */
1137 status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; 1214 flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2;
1138 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1215 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1139 1216
1140 /* start playback again */ 1217 /* start transfer again */
1141 /* FIXME: what is this value (0x0010)??? */ 1218 /* FIXME: what is this value (0x0010)??? */
1142 status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; 1219 flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;
1143 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1220 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1144#else /* NT4 */ 1221#else /* NT4 */
1145 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1222 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1146 0x0000); 1223 0x0000);
1147 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1224 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1148 DMA_PLAY_SOMETHING1); 1225 DMA_RUN_SOMETHING1);
1149 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1226 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1150 DMA_PLAY_SOMETHING1 | 1227 DMA_RUN_SOMETHING1 |
1151 DMA_PLAY_SOMETHING2); 1228 DMA_RUN_SOMETHING2);
1152 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1229 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1153 DMA_RESUME | 1230 DMA_RESUME |
1154 SOMETHING_ALMOST_ALWAYS_SET | 1231 SOMETHING_ALMOST_ALWAYS_SET |
1155 DMA_EPILOGUE_SOMETHING | 1232 DMA_EPILOGUE_SOMETHING |
1156 DMA_SOMETHING_ELSE); 1233 DMA_SOMETHING_ELSE);
1157#endif 1234#endif
1158 spin_unlock(&chip->reg_lock); 1235 spin_unlock(&chip->reg_lock);
1159 snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 1); 1236 snd_azf3328_ctrl_codec_activity(chip, codec_type, 1);
1160 1237
1161 /* now unmute WaveOut */ 1238 if (is_playback_codec) {
1162 if (!previously_muted) 1239 /* now unmute WaveOut */
1163 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); 1240 if (!previously_muted)
1241 snd_azf3328_mixer_set_mute(
1242 chip, IDX_MIXER_WAVEOUT, 0
1243 );
1244 }
1164 1245
1165 snd_azf3328_dbgplay("STARTED PLAYBACK\n"); 1246 snd_azf3328_dbgplay("STARTED %s\n", codec->name);
1166 break; 1247 break;
1167 case SNDRV_PCM_TRIGGER_RESUME: 1248 case SNDRV_PCM_TRIGGER_RESUME:
1168 snd_azf3328_dbgplay("RESUME PLAYBACK\n"); 1249 snd_azf3328_dbgplay("RESUME %s\n", codec->name);
1169 /* resume playback if we were active */ 1250 /* resume codec if we were active */
1170 spin_lock(&chip->reg_lock); 1251 spin_lock(&chip->reg_lock);
1171 if (chip->audio_stream[AZF_PLAYBACK].running) 1252 if (codec->running)
1172 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1253 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1173 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME); 1254 snd_azf3328_codec_inw(
1255 codec, IDX_IO_CODEC_DMA_FLAGS
1256 ) | DMA_RESUME
1257 );
1174 spin_unlock(&chip->reg_lock); 1258 spin_unlock(&chip->reg_lock);
1175 break; 1259 break;
1176 case SNDRV_PCM_TRIGGER_STOP: 1260 case SNDRV_PCM_TRIGGER_STOP:
1177 snd_azf3328_dbgplay("STOP PLAYBACK\n"); 1261 snd_azf3328_dbgplay("STOP %s\n", codec->name);
1178 1262
1179 /* mute WaveOut (avoid clicking during setup) */ 1263 if (is_playback_codec) {
1180 previously_muted = 1264 /* mute WaveOut (avoid clicking during setup) */
1181 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 1265 previously_muted =
1266 snd_azf3328_mixer_set_mute(
1267 chip, IDX_MIXER_WAVEOUT, 1
1268 );
1269 }
1182 1270
1183 spin_lock(&chip->reg_lock); 1271 spin_lock(&chip->reg_lock);
1184 /* first, remember current value: */ 1272 /* first, remember current value: */
1185 status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); 1273 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
1186 1274
1187 /* stop playback */ 1275 /* stop transfer */
1188 status1 &= ~DMA_RESUME; 1276 flags1 &= ~DMA_RESUME;
1189 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1277 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1190 1278
1191 /* hmm, is this really required? we're resetting the same bit 1279 /* hmm, is this really required? we're resetting the same bit
1192 * immediately thereafter... */ 1280 * immediately thereafter... */
1193 status1 |= DMA_PLAY_SOMETHING1; 1281 flags1 |= DMA_RUN_SOMETHING1;
1194 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1282 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1195 1283
1196 status1 &= ~DMA_PLAY_SOMETHING1; 1284 flags1 &= ~DMA_RUN_SOMETHING1;
1197 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1285 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
1198 spin_unlock(&chip->reg_lock); 1286 spin_unlock(&chip->reg_lock);
1199 snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0); 1287 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
1200 1288
1201 /* now unmute WaveOut */ 1289 if (is_playback_codec) {
1202 if (!previously_muted) 1290 /* now unmute WaveOut */
1203 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); 1291 if (!previously_muted)
1292 snd_azf3328_mixer_set_mute(
1293 chip, IDX_MIXER_WAVEOUT, 0
1294 );
1295 }
1204 1296
1205 snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); 1297 snd_azf3328_dbgplay("STOPPED %s\n", codec->name);
1206 break; 1298 break;
1207 case SNDRV_PCM_TRIGGER_SUSPEND: 1299 case SNDRV_PCM_TRIGGER_SUSPEND:
1208 snd_azf3328_dbgplay("SUSPEND PLAYBACK\n"); 1300 snd_azf3328_dbgplay("SUSPEND %s\n", codec->name);
1209 /* make sure playback is stopped */ 1301 /* make sure codec is stopped */
1210 snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1302 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
1211 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME); 1303 snd_azf3328_codec_inw(
1304 codec, IDX_IO_CODEC_DMA_FLAGS
1305 ) & ~DMA_RESUME
1306 );
1212 break; 1307 break;
1213 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1308 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1214 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); 1309 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
@@ -1225,172 +1320,74 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
1225 return result; 1320 return result;
1226} 1321}
1227 1322
1228/* this is just analogous to playback; I'm not quite sure whether recording
1229 * should actually be triggered like that */
1230static int 1323static int
1231snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) 1324snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd)
1232{ 1325{
1233 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1326 return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd);
1234 struct snd_pcm_runtime *runtime = substream->runtime; 1327}
1235 int result = 0;
1236 unsigned int status1;
1237
1238 snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd);
1239
1240 switch (cmd) {
1241 case SNDRV_PCM_TRIGGER_START:
1242
1243 snd_azf3328_dbgplay("START CAPTURE\n");
1244
1245 snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,
1246 runtime->rate,
1247 snd_pcm_format_width(runtime->format),
1248 runtime->channels);
1249
1250 spin_lock(&chip->reg_lock);
1251 /* first, remember current value: */
1252 status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);
1253
1254 /* stop recording */
1255 status1 &= ~DMA_RESUME;
1256 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
1257
1258 /* FIXME: clear interrupts or what??? */
1259 snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff);
1260 spin_unlock(&chip->reg_lock);
1261
1262 snd_azf3328_setdmaa(chip, runtime->dma_addr,
1263 snd_pcm_lib_period_bytes(substream),
1264 snd_pcm_lib_buffer_bytes(substream),
1265 AZF_CAPTURE);
1266
1267 spin_lock(&chip->reg_lock);
1268#ifdef WIN9X
1269 /* FIXME: enable playback/recording??? */
1270 status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;
1271 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
1272
1273 /* start capture again */
1274 /* FIXME: what is this value (0x0010)??? */
1275 status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;
1276 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
1277#else
1278 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1279 0x0000);
1280 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1281 DMA_PLAY_SOMETHING1);
1282 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1283 DMA_PLAY_SOMETHING1 |
1284 DMA_PLAY_SOMETHING2);
1285 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1286 DMA_RESUME |
1287 SOMETHING_ALMOST_ALWAYS_SET |
1288 DMA_EPILOGUE_SOMETHING |
1289 DMA_SOMETHING_ELSE);
1290#endif
1291 spin_unlock(&chip->reg_lock);
1292 snd_azf3328_codec_activity(chip, AZF_CAPTURE, 1);
1293
1294 snd_azf3328_dbgplay("STARTED CAPTURE\n");
1295 break;
1296 case SNDRV_PCM_TRIGGER_RESUME:
1297 snd_azf3328_dbgplay("RESUME CAPTURE\n");
1298 /* resume recording if we were active */
1299 spin_lock(&chip->reg_lock);
1300 if (chip->audio_stream[AZF_CAPTURE].running)
1301 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1302 snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME);
1303 spin_unlock(&chip->reg_lock);
1304 break;
1305 case SNDRV_PCM_TRIGGER_STOP:
1306 snd_azf3328_dbgplay("STOP CAPTURE\n");
1307
1308 spin_lock(&chip->reg_lock);
1309 /* first, remember current value: */
1310 status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);
1311
1312 /* stop recording */
1313 status1 &= ~DMA_RESUME;
1314 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
1315
1316 status1 |= DMA_PLAY_SOMETHING1;
1317 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
1318
1319 status1 &= ~DMA_PLAY_SOMETHING1;
1320 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
1321 spin_unlock(&chip->reg_lock);
1322 snd_azf3328_codec_activity(chip, AZF_CAPTURE, 0);
1323 1328
1324 snd_azf3328_dbgplay("STOPPED CAPTURE\n"); 1329static int
1325 break; 1330snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd)
1326 case SNDRV_PCM_TRIGGER_SUSPEND: 1331{
1327 snd_azf3328_dbgplay("SUSPEND CAPTURE\n"); 1332 return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd);
1328 /* make sure recording is stopped */ 1333}
1329 snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
1330 snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME);
1331 break;
1332 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1333 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
1334 break;
1335 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1336 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
1337 break;
1338 default:
1339 printk(KERN_ERR "FIXME: unknown trigger mode!\n");
1340 return -EINVAL;
1341 }
1342 1334
1343 snd_azf3328_dbgcallleave(); 1335static int
1344 return result; 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);
1345} 1339}
1346 1340
1347static snd_pcm_uframes_t 1341static snd_pcm_uframes_t
1348snd_azf3328_playback_pointer(struct snd_pcm_substream *substream) 1342snd_azf3328_codec_pointer(struct snd_pcm_substream *substream,
1343 enum snd_azf3328_codec_type codec_type
1344)
1349{ 1345{
1350 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1346 const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1347 const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
1351 unsigned long bufptr, result; 1348 unsigned long bufptr, result;
1352 snd_pcm_uframes_t frmres; 1349 snd_pcm_uframes_t frmres;
1353 1350
1354#ifdef QUERY_HARDWARE 1351#ifdef QUERY_HARDWARE
1355 bufptr = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_START_1); 1352 bufptr = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1);
1356#else 1353#else
1357 bufptr = substream->runtime->dma_addr; 1354 bufptr = substream->runtime->dma_addr;
1358#endif 1355#endif
1359 result = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_CURRPOS); 1356 result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS);
1360 1357
1361 /* calculate offset */ 1358 /* calculate offset */
1362 result -= bufptr; 1359 result -= bufptr;
1363 frmres = bytes_to_frames( substream->runtime, result); 1360 frmres = bytes_to_frames( substream->runtime, result);
1364 snd_azf3328_dbgplay("PLAY @ 0x%8lx, frames %8ld\n", result, frmres); 1361 snd_azf3328_dbgplay("%s @ 0x%8lx, frames %8ld\n",
1362 codec->name, result, frmres);
1365 return frmres; 1363 return frmres;
1366} 1364}
1367 1365
1368static snd_pcm_uframes_t 1366static snd_pcm_uframes_t
1369snd_azf3328_capture_pointer(struct snd_pcm_substream *substream) 1367snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream)
1370{ 1368{
1371 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1369 return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK);
1372 unsigned long bufptr, result; 1370}
1373 snd_pcm_uframes_t frmres;
1374 1371
1375#ifdef QUERY_HARDWARE 1372static snd_pcm_uframes_t
1376 bufptr = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_START_1); 1373snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream)
1377#else 1374{
1378 bufptr = substream->runtime->dma_addr; 1375 return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE);
1379#endif 1376}
1380 result = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_CURRPOS);
1381 1377
1382 /* calculate offset */ 1378static snd_pcm_uframes_t
1383 result -= bufptr; 1379snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream)
1384 frmres = bytes_to_frames( substream->runtime, result); 1380{
1385 snd_azf3328_dbgplay("REC @ 0x%8lx, frames %8ld\n", result, frmres); 1381 return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT);
1386 return frmres;
1387} 1382}
1388 1383
1389/******************************************************************/ 1384/******************************************************************/
1390 1385
1391#ifdef SUPPORT_GAMEPORT 1386#ifdef SUPPORT_GAMEPORT
1392static inline void 1387static inline void
1393snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, int enable) 1388snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip,
1389 bool enable
1390)
1394{ 1391{
1395 snd_azf3328_io_reg_setb( 1392 snd_azf3328_io_reg_setb(
1396 chip->game_io+IDX_GAME_HWCONFIG, 1393 chip->game_io+IDX_GAME_HWCONFIG,
@@ -1400,7 +1397,9 @@ snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, int enable)
1400} 1397}
1401 1398
1402static inline void 1399static inline void
1403snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, int enable) 1400snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip,
1401 bool enable
1402)
1404{ 1403{
1405 snd_azf3328_io_reg_setb( 1404 snd_azf3328_io_reg_setb(
1406 chip->game_io+IDX_GAME_HWCONFIG, 1405 chip->game_io+IDX_GAME_HWCONFIG,
@@ -1409,10 +1408,27 @@ snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, int enable)
1409 ); 1408 );
1410} 1409}
1411 1410
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
1412static inline void 1428static inline void
1413snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, int enable) 1429snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, bool enable)
1414{ 1430{
1415 snd_azf3328_codec_reg_6AH_update( 1431 snd_azf3328_ctrl_reg_6AH_update(
1416 chip, IO_6A_SOMETHING2_GAMEPORT, enable 1432 chip, IO_6A_SOMETHING2_GAMEPORT, enable
1417 ); 1433 );
1418} 1434}
@@ -1447,6 +1463,8 @@ snd_azf3328_gameport_open(struct gameport *gameport, int mode)
1447 break; 1463 break;
1448 } 1464 }
1449 1465
1466 snd_azf3328_gameport_set_counter_frequency(chip,
1467 GAME_HWCFG_ADC_COUNTER_FREQ_STD);
1450 snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0)); 1468 snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0));
1451 1469
1452 return res; 1470 return res;
@@ -1458,6 +1476,8 @@ snd_azf3328_gameport_close(struct gameport *gameport)
1458 struct snd_azf3328 *chip = gameport_get_port_data(gameport); 1476 struct snd_azf3328 *chip = gameport_get_port_data(gameport);
1459 1477
1460 snd_azf3328_dbggame("gameport_close\n"); 1478 snd_azf3328_dbggame("gameport_close\n");
1479 snd_azf3328_gameport_set_counter_frequency(chip,
1480 GAME_HWCFG_ADC_COUNTER_FREQ_1_200);
1461 snd_azf3328_gameport_axis_circuit_enable(chip, 0); 1481 snd_azf3328_gameport_axis_circuit_enable(chip, 0);
1462} 1482}
1463 1483
@@ -1491,7 +1511,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport,
1491 1511
1492 val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG); 1512 val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG);
1493 if (val & GAME_AXES_SAMPLING_READY) { 1513 if (val & GAME_AXES_SAMPLING_READY) {
1494 for (i = 0; i < 4; ++i) { 1514 for (i = 0; i < ARRAY_SIZE(chip->axes); ++i) {
1495 /* configure the axis to read */ 1515 /* configure the axis to read */
1496 val = (i << 4) | 0x0f; 1516 val = (i << 4) | 0x0f;
1497 snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val); 1517 snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val);
@@ -1514,7 +1534,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport,
1514 snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff); 1534 snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff);
1515 spin_unlock_irqrestore(&chip->reg_lock, flags); 1535 spin_unlock_irqrestore(&chip->reg_lock, flags);
1516 1536
1517 for (i = 0; i < 4; i++) { 1537 for (i = 0; i < ARRAY_SIZE(chip->axes); i++) {
1518 axes[i] = chip->axes[i]; 1538 axes[i] = chip->axes[i];
1519 if (axes[i] == 0xffff) 1539 if (axes[i] == 0xffff)
1520 axes[i] = -1; 1540 axes[i] = -1;
@@ -1552,6 +1572,8 @@ snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
1552 /* DISABLE legacy address: we don't need it! */ 1572 /* DISABLE legacy address: we don't need it! */
1553 snd_azf3328_gameport_legacy_address_enable(chip, 0); 1573 snd_azf3328_gameport_legacy_address_enable(chip, 0);
1554 1574
1575 snd_azf3328_gameport_set_counter_frequency(chip,
1576 GAME_HWCFG_ADC_COUNTER_FREQ_1_200);
1555 snd_azf3328_gameport_axis_circuit_enable(chip, 0); 1577 snd_azf3328_gameport_axis_circuit_enable(chip, 0);
1556 1578
1557 gameport_register_port(chip->gameport); 1579 gameport_register_port(chip->gameport);
@@ -1591,29 +1613,69 @@ snd_azf3328_irq_log_unknown_type(u8 which)
1591 ); 1613 );
1592} 1614}
1593 1615
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
1594static irqreturn_t 1658static irqreturn_t
1595snd_azf3328_interrupt(int irq, void *dev_id) 1659snd_azf3328_interrupt(int irq, void *dev_id)
1596{ 1660{
1597 struct snd_azf3328 *chip = dev_id; 1661 struct snd_azf3328 *chip = dev_id;
1598 u8 status, which; 1662 u8 status;
1599#if DEBUG_PLAY_REC 1663#if DEBUG_PLAY_REC
1600 static unsigned long irq_count; 1664 static unsigned long irq_count;
1601#endif 1665#endif
1602 1666
1603 status = snd_azf3328_codec_inb(chip, IDX_IO_IRQSTATUS); 1667 status = snd_azf3328_ctrl_inb(chip, IDX_IO_IRQSTATUS);
1604 1668
1605 /* fast path out, to ease interrupt sharing */ 1669 /* fast path out, to ease interrupt sharing */
1606 if (!(status & 1670 if (!(status &
1607 (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER) 1671 (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT
1672 |IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER)
1608 )) 1673 ))
1609 return IRQ_NONE; /* must be interrupt for another device */ 1674 return IRQ_NONE; /* must be interrupt for another device */
1610 1675
1611 snd_azf3328_dbgplay( 1676 snd_azf3328_dbgplay(
1612 "irq_count %ld! IDX_IO_PLAY_FLAGS %04x, " 1677 "irq_count %ld! IDX_IO_IRQSTATUS %04x\n",
1613 "IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n",
1614 irq_count++ /* debug-only */, 1678 irq_count++ /* debug-only */,
1615 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS),
1616 snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE),
1617 status 1679 status
1618 ); 1680 );
1619 1681
@@ -1626,63 +1688,24 @@ snd_azf3328_interrupt(int irq, void *dev_id)
1626 snd_timer_interrupt(chip->timer, chip->timer->sticks); 1688 snd_timer_interrupt(chip->timer, chip->timer->sticks);
1627 /* ACK timer */ 1689 /* ACK timer */
1628 spin_lock(&chip->reg_lock); 1690 spin_lock(&chip->reg_lock);
1629 snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); 1691 snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07);
1630 spin_unlock(&chip->reg_lock); 1692 spin_unlock(&chip->reg_lock);
1631 snd_azf3328_dbgplay("azt3328: timer IRQ\n"); 1693 snd_azf3328_dbgplay("azt3328: timer IRQ\n");
1632 } 1694 }
1633 if (status & IRQ_PLAYBACK) {
1634 spin_lock(&chip->reg_lock);
1635 which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE);
1636 /* ack all IRQ types immediately */
1637 snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which);
1638 spin_unlock(&chip->reg_lock);
1639 1695
1640 if (chip->pcm && chip->audio_stream[AZF_PLAYBACK].substream) { 1696 if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT))
1641 snd_pcm_period_elapsed( 1697 snd_azf3328_codec_interrupt(chip, status);
1642 chip->audio_stream[AZF_PLAYBACK].substream
1643 );
1644 snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n",
1645 which,
1646 snd_azf3328_codec_inl(
1647 chip, IDX_IO_PLAY_DMA_CURRPOS
1648 )
1649 );
1650 } else
1651 printk(KERN_WARNING "azt3328: irq handler problem!\n");
1652 if (which & IRQ_PLAY_SOMETHING)
1653 snd_azf3328_irq_log_unknown_type(which);
1654 }
1655 if (status & IRQ_RECORDING) {
1656 spin_lock(&chip->reg_lock);
1657 which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE);
1658 /* ack all IRQ types immediately */
1659 snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which);
1660 spin_unlock(&chip->reg_lock);
1661 1698
1662 if (chip->pcm && chip->audio_stream[AZF_CAPTURE].substream) {
1663 snd_pcm_period_elapsed(
1664 chip->audio_stream[AZF_CAPTURE].substream
1665 );
1666 snd_azf3328_dbgplay("REC period done (#%x), @ %x\n",
1667 which,
1668 snd_azf3328_codec_inl(
1669 chip, IDX_IO_REC_DMA_CURRPOS
1670 )
1671 );
1672 } else
1673 printk(KERN_WARNING "azt3328: irq handler problem!\n");
1674 if (which & IRQ_REC_SOMETHING)
1675 snd_azf3328_irq_log_unknown_type(which);
1676 }
1677 if (status & IRQ_GAMEPORT) 1699 if (status & IRQ_GAMEPORT)
1678 snd_azf3328_gameport_interrupt(chip); 1700 snd_azf3328_gameport_interrupt(chip);
1701
1679 /* MPU401 has less critical IRQ requirements 1702 /* MPU401 has less critical IRQ requirements
1680 * than timer and playback/recording, right? */ 1703 * than timer and playback/recording, right? */
1681 if (status & IRQ_MPU401) { 1704 if (status & IRQ_MPU401) {
1682 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); 1705 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
1683 1706
1684 /* hmm, do we have to ack the IRQ here somehow? 1707 /* hmm, do we have to ack the IRQ here somehow?
1685 * If so, then I don't know how... */ 1708 * If so, then I don't know how yet... */
1686 snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n"); 1709 snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n");
1687 } 1710 }
1688 return IRQ_HANDLED; 1711 return IRQ_HANDLED;
@@ -1690,7 +1713,11 @@ snd_azf3328_interrupt(int irq, void *dev_id)
1690 1713
1691/*****************************************************************/ 1714/*****************************************************************/
1692 1715
1693static const struct snd_pcm_hardware snd_azf3328_playback = 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 =
1694{ 1721{
1695 /* FIXME!! Correct? */ 1722 /* FIXME!! Correct? */
1696 .info = SNDRV_PCM_INFO_MMAP | 1723 .info = SNDRV_PCM_INFO_MMAP |
@@ -1718,31 +1745,6 @@ static const struct snd_pcm_hardware snd_azf3328_playback =
1718 .fifo_size = 0, 1745 .fifo_size = 0,
1719}; 1746};
1720 1747
1721static const struct snd_pcm_hardware snd_azf3328_capture =
1722{
1723 /* FIXME */
1724 .info = SNDRV_PCM_INFO_MMAP |
1725 SNDRV_PCM_INFO_INTERLEAVED |
1726 SNDRV_PCM_INFO_MMAP_VALID,
1727 .formats = SNDRV_PCM_FMTBIT_S8 |
1728 SNDRV_PCM_FMTBIT_U8 |
1729 SNDRV_PCM_FMTBIT_S16_LE |
1730 SNDRV_PCM_FMTBIT_U16_LE,
1731 .rates = SNDRV_PCM_RATE_5512 |
1732 SNDRV_PCM_RATE_8000_48000 |
1733 SNDRV_PCM_RATE_KNOT,
1734 .rate_min = AZF_FREQ_4000,
1735 .rate_max = AZF_FREQ_66200,
1736 .channels_min = 1,
1737 .channels_max = 2,
1738 .buffer_bytes_max = 65536,
1739 .period_bytes_min = 64,
1740 .period_bytes_max = 65536,
1741 .periods_min = 1,
1742 .periods_max = 1024,
1743 .fifo_size = 0,
1744};
1745
1746 1748
1747static unsigned int snd_azf3328_fixed_rates[] = { 1749static unsigned int snd_azf3328_fixed_rates[] = {
1748 AZF_FREQ_4000, 1750 AZF_FREQ_4000,
@@ -1770,14 +1772,19 @@ static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = {
1770/*****************************************************************/ 1772/*****************************************************************/
1771 1773
1772static int 1774static int
1773snd_azf3328_playback_open(struct snd_pcm_substream *substream) 1775snd_azf3328_pcm_open(struct snd_pcm_substream *substream,
1776 enum snd_azf3328_codec_type codec_type
1777)
1774{ 1778{
1775 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1779 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1776 struct snd_pcm_runtime *runtime = substream->runtime; 1780 struct snd_pcm_runtime *runtime = substream->runtime;
1777 1781
1778 snd_azf3328_dbgcallenter(); 1782 snd_azf3328_dbgcallenter();
1779 chip->audio_stream[AZF_PLAYBACK].substream = substream; 1783 chip->codecs[codec_type].substream = substream;
1780 runtime->hw = snd_azf3328_playback; 1784
1785 /* same parameters for all our codecs - at least we think so... */
1786 runtime->hw = snd_azf3328_hardware;
1787
1781 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 1788 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1782 &snd_azf3328_hw_constraints_rates); 1789 &snd_azf3328_hw_constraints_rates);
1783 snd_azf3328_dbgcallleave(); 1790 snd_azf3328_dbgcallleave();
@@ -1785,40 +1792,52 @@ snd_azf3328_playback_open(struct snd_pcm_substream *substream)
1785} 1792}
1786 1793
1787static int 1794static int
1795snd_azf3328_playback_open(struct snd_pcm_substream *substream)
1796{
1797 return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK);
1798}
1799
1800static int
1788snd_azf3328_capture_open(struct snd_pcm_substream *substream) 1801snd_azf3328_capture_open(struct snd_pcm_substream *substream)
1789{ 1802{
1790 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1803 return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE);
1791 struct snd_pcm_runtime *runtime = substream->runtime; 1804}
1792 1805
1793 snd_azf3328_dbgcallenter(); 1806static int
1794 chip->audio_stream[AZF_CAPTURE].substream = substream; 1807snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream)
1795 runtime->hw = snd_azf3328_capture; 1808{
1796 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 1809 return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT);
1797 &snd_azf3328_hw_constraints_rates);
1798 snd_azf3328_dbgcallleave();
1799 return 0;
1800} 1810}
1801 1811
1802static int 1812static int
1803snd_azf3328_playback_close(struct snd_pcm_substream *substream) 1813snd_azf3328_pcm_close(struct snd_pcm_substream *substream,
1814 enum snd_azf3328_codec_type codec_type
1815)
1804{ 1816{
1805 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1817 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
1806 1818
1807 snd_azf3328_dbgcallenter(); 1819 snd_azf3328_dbgcallenter();
1808 chip->audio_stream[AZF_PLAYBACK].substream = NULL; 1820 chip->codecs[codec_type].substream = NULL;
1809 snd_azf3328_dbgcallleave(); 1821 snd_azf3328_dbgcallleave();
1810 return 0; 1822 return 0;
1811} 1823}
1812 1824
1813static int 1825static int
1826snd_azf3328_playback_close(struct snd_pcm_substream *substream)
1827{
1828 return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK);
1829}
1830
1831static int
1814snd_azf3328_capture_close(struct snd_pcm_substream *substream) 1832snd_azf3328_capture_close(struct snd_pcm_substream *substream)
1815{ 1833{
1816 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1834 return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE);
1835}
1817 1836
1818 snd_azf3328_dbgcallenter(); 1837static int
1819 chip->audio_stream[AZF_CAPTURE].substream = NULL; 1838snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream)
1820 snd_azf3328_dbgcallleave(); 1839{
1821 return 0; 1840 return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT);
1822} 1841}
1823 1842
1824/******************************************************************/ 1843/******************************************************************/
@@ -1829,9 +1848,9 @@ static struct snd_pcm_ops snd_azf3328_playback_ops = {
1829 .ioctl = snd_pcm_lib_ioctl, 1848 .ioctl = snd_pcm_lib_ioctl,
1830 .hw_params = snd_azf3328_hw_params, 1849 .hw_params = snd_azf3328_hw_params,
1831 .hw_free = snd_azf3328_hw_free, 1850 .hw_free = snd_azf3328_hw_free,
1832 .prepare = snd_azf3328_playback_prepare, 1851 .prepare = snd_azf3328_codec_prepare,
1833 .trigger = snd_azf3328_playback_trigger, 1852 .trigger = snd_azf3328_codec_playback_trigger,
1834 .pointer = snd_azf3328_playback_pointer 1853 .pointer = snd_azf3328_codec_playback_pointer
1835}; 1854};
1836 1855
1837static struct snd_pcm_ops snd_azf3328_capture_ops = { 1856static struct snd_pcm_ops snd_azf3328_capture_ops = {
@@ -1840,30 +1859,67 @@ static struct snd_pcm_ops snd_azf3328_capture_ops = {
1840 .ioctl = snd_pcm_lib_ioctl, 1859 .ioctl = snd_pcm_lib_ioctl,
1841 .hw_params = snd_azf3328_hw_params, 1860 .hw_params = snd_azf3328_hw_params,
1842 .hw_free = snd_azf3328_hw_free, 1861 .hw_free = snd_azf3328_hw_free,
1843 .prepare = snd_azf3328_capture_prepare, 1862 .prepare = snd_azf3328_codec_prepare,
1844 .trigger = snd_azf3328_capture_trigger, 1863 .trigger = snd_azf3328_codec_capture_trigger,
1845 .pointer = snd_azf3328_capture_pointer 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
1846}; 1876};
1847 1877
1848static int __devinit 1878static int __devinit
1849snd_azf3328_pcm(struct snd_azf3328 *chip, int device) 1879snd_azf3328_pcm(struct snd_azf3328 *chip)
1850{ 1880{
1881enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */
1882
1851 struct snd_pcm *pcm; 1883 struct snd_pcm *pcm;
1852 int err; 1884 int err;
1853 1885
1854 snd_azf3328_dbgcallenter(); 1886 snd_azf3328_dbgcallenter();
1855 if ((err = snd_pcm_new(chip->card, "AZF3328 DSP", device, 1, 1, &pcm)) < 0) 1887
1888 err = snd_pcm_new(chip->card, "AZF3328 DSP", AZF_PCMDEV_STD,
1889 1, 1, &pcm);
1890 if (err < 0)
1856 return err; 1891 return err;
1857 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_azf3328_playback_ops); 1892 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1858 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_azf3328_capture_ops); 1893 &snd_azf3328_playback_ops);
1894 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
1895 &snd_azf3328_capture_ops);
1859 1896
1860 pcm->private_data = chip; 1897 pcm->private_data = chip;
1861 pcm->info_flags = 0; 1898 pcm->info_flags = 0;
1862 strcpy(pcm->name, chip->card->shortname); 1899 strcpy(pcm->name, chip->card->shortname);
1863 chip->pcm = pcm; 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;
1864 1903
1865 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 1904 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1866 snd_dma_pci_data(chip->pci), 64*1024, 64*1024); 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);
1867 1923
1868 snd_azf3328_dbgcallleave(); 1924 snd_azf3328_dbgcallleave();
1869 return 0; 1925 return 0;
@@ -1902,7 +1958,7 @@ snd_azf3328_timer_start(struct snd_timer *timer)
1902 snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay); 1958 snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay);
1903 delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; 1959 delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE;
1904 spin_lock_irqsave(&chip->reg_lock, flags); 1960 spin_lock_irqsave(&chip->reg_lock, flags);
1905 snd_azf3328_codec_outl(chip, IDX_IO_TIMER_VALUE, delay); 1961 snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay);
1906 spin_unlock_irqrestore(&chip->reg_lock, flags); 1962 spin_unlock_irqrestore(&chip->reg_lock, flags);
1907 snd_azf3328_dbgcallleave(); 1963 snd_azf3328_dbgcallleave();
1908 return 0; 1964 return 0;
@@ -1919,7 +1975,7 @@ snd_azf3328_timer_stop(struct snd_timer *timer)
1919 spin_lock_irqsave(&chip->reg_lock, flags); 1975 spin_lock_irqsave(&chip->reg_lock, flags);
1920 /* disable timer countdown and interrupt */ 1976 /* disable timer countdown and interrupt */
1921 /* FIXME: should we write TIMER_IRQ_ACK here? */ 1977 /* FIXME: should we write TIMER_IRQ_ACK here? */
1922 snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); 1978 snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0);
1923 spin_unlock_irqrestore(&chip->reg_lock, flags); 1979 spin_unlock_irqrestore(&chip->reg_lock, flags);
1924 snd_azf3328_dbgcallleave(); 1980 snd_azf3328_dbgcallleave();
1925 return 0; 1981 return 0;
@@ -2048,9 +2104,9 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
2048 u16 tmp; 2104 u16 tmp;
2049 2105
2050 snd_azf3328_dbgmisc( 2106 snd_azf3328_dbgmisc(
2051 "codec_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, " 2107 "ctrl_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, "
2052 "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n", 2108 "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n",
2053 chip->codec_io, chip->game_io, chip->mpu_io, 2109 chip->ctrl_io, chip->game_io, chip->mpu_io,
2054 chip->opl3_io, chip->mixer_io, chip->irq 2110 chip->opl3_io, chip->mixer_io, chip->irq
2055 ); 2111 );
2056 2112
@@ -2083,9 +2139,9 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
2083 inb(0x38c + tmp) 2139 inb(0x38c + tmp)
2084 ); 2140 );
2085 2141
2086 for (tmp = 0; tmp < AZF_IO_SIZE_CODEC; tmp += 2) 2142 for (tmp = 0; tmp < AZF_IO_SIZE_CTRL; tmp += 2)
2087 snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n", 2143 snd_azf3328_dbgmisc("ctrl 0x%02x: 0x%04x\n",
2088 tmp, snd_azf3328_codec_inw(chip, tmp) 2144 tmp, snd_azf3328_ctrl_inw(chip, tmp)
2089 ); 2145 );
2090 2146
2091 for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2) 2147 for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2)
@@ -2106,7 +2162,8 @@ snd_azf3328_create(struct snd_card *card,
2106 static struct snd_device_ops ops = { 2162 static struct snd_device_ops ops = {
2107 .dev_free = snd_azf3328_dev_free, 2163 .dev_free = snd_azf3328_dev_free,
2108 }; 2164 };
2109 u16 tmp; 2165 u8 dma_init;
2166 enum snd_azf3328_codec_type codec_type;
2110 2167
2111 *rchip = NULL; 2168 *rchip = NULL;
2112 2169
@@ -2138,14 +2195,21 @@ snd_azf3328_create(struct snd_card *card,
2138 if (err < 0) 2195 if (err < 0)
2139 goto out_err; 2196 goto out_err;
2140 2197
2141 chip->codec_io = pci_resource_start(pci, 0); 2198 chip->ctrl_io = pci_resource_start(pci, 0);
2142 chip->game_io = pci_resource_start(pci, 1); 2199 chip->game_io = pci_resource_start(pci, 1);
2143 chip->mpu_io = pci_resource_start(pci, 2); 2200 chip->mpu_io = pci_resource_start(pci, 2);
2144 chip->opl3_io = pci_resource_start(pci, 3); 2201 chip->opl3_io = pci_resource_start(pci, 3);
2145 chip->mixer_io = pci_resource_start(pci, 4); 2202 chip->mixer_io = pci_resource_start(pci, 4);
2146 2203
2147 chip->audio_stream[AZF_PLAYBACK].portbase = chip->codec_io + 0x00; 2204 chip->codecs[AZF_CODEC_PLAYBACK].io_base =
2148 chip->audio_stream[AZF_CAPTURE].portbase = chip->codec_io + 0x20; 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";
2149 2213
2150 if (request_irq(pci->irq, snd_azf3328_interrupt, 2214 if (request_irq(pci->irq, snd_azf3328_interrupt,
2151 IRQF_SHARED, card->shortname, chip)) { 2215 IRQF_SHARED, card->shortname, chip)) {
@@ -2168,20 +2232,25 @@ snd_azf3328_create(struct snd_card *card,
2168 if (err < 0) 2232 if (err < 0)
2169 goto out_err; 2233 goto out_err;
2170 2234
2171 /* shutdown codecs to save power */ 2235 /* standard codec init stuff */
2172 /* have snd_azf3328_codec_activity() act properly */ 2236 /* default DMA init value */
2173 chip->audio_stream[AZF_PLAYBACK].running = 1; 2237 dma_init = DMA_RUN_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE;
2174 snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0); 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];
2175 2243
2176 /* standard chip init stuff */ 2244 /* shutdown codecs to save power */
2177 /* default IRQ init value */ 2245 /* have ...ctrl_codec_activity() act properly */
2178 tmp = DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; 2246 codec->running = 1;
2247 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
2179 2248
2180 spin_lock_irq(&chip->reg_lock); 2249 spin_lock_irq(&chip->reg_lock);
2181 snd_azf3328_codec_outb(chip, IDX_IO_PLAY_FLAGS, tmp); 2250 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS,
2182 snd_azf3328_codec_outb(chip, IDX_IO_REC_FLAGS, tmp); 2251 dma_init);
2183 snd_azf3328_codec_outb(chip, IDX_IO_SOMETHING_FLAGS, tmp); 2252 spin_unlock_irq(&chip->reg_lock);
2184 spin_unlock_irq(&chip->reg_lock); 2253 }
2185 2254
2186 snd_card_set_dev(card, &pci->dev); 2255 snd_card_set_dev(card, &pci->dev);
2187 2256
@@ -2244,7 +2313,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
2244 if (err < 0) 2313 if (err < 0)
2245 goto out_err; 2314 goto out_err;
2246 2315
2247 err = snd_azf3328_pcm(chip, 0); 2316 err = snd_azf3328_pcm(chip);
2248 if (err < 0) 2317 if (err < 0)
2249 goto out_err; 2318 goto out_err;
2250 2319
@@ -2266,7 +2335,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
2266 opl3->private_data = chip; 2335 opl3->private_data = chip;
2267 2336
2268 sprintf(card->longname, "%s at 0x%lx, irq %i", 2337 sprintf(card->longname, "%s at 0x%lx, irq %i",
2269 card->shortname, chip->codec_io, chip->irq); 2338 card->shortname, chip->ctrl_io, chip->irq);
2270 2339
2271 err = snd_card_register(card); 2340 err = snd_card_register(card);
2272 if (err < 0) 2341 if (err < 0)
@@ -2317,7 +2386,8 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
2317 2386
2318 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 2387 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
2319 2388
2320 snd_pcm_suspend_all(chip->pcm); 2389 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);
2390 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);
2321 2391
2322 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) 2392 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
2323 chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2); 2393 chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2);
@@ -2326,11 +2396,11 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
2326 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); 2396 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
2327 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 2397 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
2328 2398
2329 for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg) 2399 for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg)
2330 chip->saved_regs_codec[reg] = inw(chip->codec_io + reg * 2); 2400 chip->saved_regs_ctrl[reg] = inw(chip->ctrl_io + reg * 2);
2331 2401
2332 /* manually store the one currently relevant write-only reg, too */ 2402 /* manually store the one currently relevant write-only reg, too */
2333 chip->saved_regs_codec[IDX_IO_6AH / 2] = chip->shadow_reg_codec_6AH; 2403 chip->saved_regs_ctrl[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH;
2334 2404
2335 for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg) 2405 for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg)
2336 chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2); 2406 chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2);
@@ -2349,7 +2419,7 @@ static int
2349snd_azf3328_resume(struct pci_dev *pci) 2419snd_azf3328_resume(struct pci_dev *pci)
2350{ 2420{
2351 struct snd_card *card = pci_get_drvdata(pci); 2421 struct snd_card *card = pci_get_drvdata(pci);
2352 struct snd_azf3328 *chip = card->private_data; 2422 const struct snd_azf3328 *chip = card->private_data;
2353 unsigned reg; 2423 unsigned reg;
2354 2424
2355 pci_set_power_state(pci, PCI_D0); 2425 pci_set_power_state(pci, PCI_D0);
@@ -2370,8 +2440,8 @@ snd_azf3328_resume(struct pci_dev *pci)
2370 outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2); 2440 outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2);
2371 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) 2441 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
2372 outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2); 2442 outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2);
2373 for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg) 2443 for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg)
2374 outw(chip->saved_regs_codec[reg], chip->codec_io + reg * 2); 2444 outw(chip->saved_regs_ctrl[reg], chip->ctrl_io + reg * 2);
2375 2445
2376 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 2446 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
2377 return 0; 2447 return 0;