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

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>

authored by

Andreas Mohr and committed by
Takashi Iwai
dfbf9511 3eff8958

+561 -498
+521 -451
sound/pci/azt3328.c
··· 1 1 /* 2 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 5 * Framework borrowed from Bart Hartgers's als4000.c. 6 6 * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), ··· 9 9 * PCI168 A(W), sub ID 1800 10 10 * PCI168 A/AP, sub ID 8000 11 11 * Please give me feedback in case you try my driver with one of these!! 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) 12 19 * 13 20 * GPL LICENSE 14 21 * This program is free software; you can redistribute it and/or modify ··· 78 71 * - built-in General DirectX timer having a 20 bits counter 79 72 * with 1us resolution (see below!) 80 73 * - I2S serial output port for external DAC 74 + * [FIXME: 3.3V or 5V level? maximum rate is 66.2kHz right?] 81 75 * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI 82 76 * - supports hardware volume control 83 77 * - single chip low cost solution (128 pin QFP) 84 - * - supports programmable Sub-vendor and Sub-system ID 78 + * - supports programmable Sub-vendor and Sub-system ID [24C02 SEEPROM chip] 85 79 * required for Microsoft's logo compliance (FIXME: where?) 86 80 * At least the Trident 4D Wave DX has one bit somewhere 87 81 * to enable writes to PCI subsystem VID registers, that should be it. ··· 90 82 * some custom data starting at 0x80. What kind of config settings 91 83 * are located in our extended PCI space anyway?? 92 84 * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms 85 + * [TDA1517P chip] 93 86 * 94 87 * Note that this driver now is actually *better* than the Windows driver, 95 88 * since it additionally supports the card's 1MHz DirectX timer - just try ··· 155 146 * to read the Digital Enhanced Game Port. Not sure whether it is fixable. 156 147 * 157 148 * TODO 149 + * - use PCI_VDEVICE 150 + * - verify driver status on x86_64 151 + * - test multi-card driver operation 152 + * - (ab)use 1MHz DirectX timer as kernel clocksource 158 153 * - test MPU401 MIDI playback etc. 159 154 * - add more power micro-management (disable various units of the card 160 - * as long as they're unused). However this requires more I/O ports which I 161 - * haven't figured out yet and which thus might not even exist... 155 + * as long as they're unused, to improve audio quality and save power). 156 + * However this requires more I/O ports which I haven't figured out yet 157 + * and which thus might not even exist... 162 158 * The standard suspend/resume functionality could probably make use of 163 159 * some improvement, too... 164 160 * - figure out what all unknown port bits are responsible for ··· 198 184 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) 199 185 #define SUPPORT_GAMEPORT 1 200 186 #endif 187 + 188 + /* === Debug settings === 189 + Further diagnostic functionality than the settings below 190 + does not need to be provided, since one can easily write a bash script 191 + to dump the card's I/O ports (those listed in lspci -v -v): 192 + function dump() 193 + { 194 + local descr=$1; local addr=$2; local count=$3 195 + 196 + echo "${descr}: ${count} @ ${addr}:" 197 + dd if=/dev/port skip=$[${addr}] count=${count} bs=1 2>/dev/null| hexdump -C 198 + } 199 + and then use something like 200 + "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8", 201 + "dump codec00 0xa800 32", "dump mixer 0xb800 64", "dump synth 0xbc00 8", 202 + possibly within a "while true; do ... sleep 1; done" loop. 203 + Tweaking ports could be done using 204 + VALSTRING="`printf "%02x" $value`" 205 + printf "\x""$VALSTRING"|dd of=/dev/port seek=$[${addr}] bs=1 2>/dev/null 206 + */ 201 207 202 208 #define DEBUG_MISC 0 203 209 #define DEBUG_CALLS 0 ··· 284 250 module_param(seqtimer_scaling, int, 0444); 285 251 MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); 286 252 287 - struct snd_azf3328_audio_stream { 253 + struct snd_azf3328_codec_data { 254 + unsigned long io_base; 288 255 struct snd_pcm_substream *substream; 289 - int enabled; 290 - int running; 291 - unsigned long portbase; 256 + bool running; 257 + const char *name; 292 258 }; 293 259 294 - enum snd_azf3328_stream_index { 295 - AZF_PLAYBACK = 0, 296 - AZF_CAPTURE = 1, 260 + enum snd_azf3328_codec_type { 261 + AZF_CODEC_PLAYBACK = 0, 262 + AZF_CODEC_CAPTURE = 1, 263 + AZF_CODEC_I2S_OUT = 2, 297 264 }; 298 265 299 266 struct snd_azf3328 { 300 267 /* often-used fields towards beginning, then grouped */ 301 268 302 - unsigned long codec_io; /* usually 0xb000, size 128 */ 269 + unsigned long ctrl_io; /* usually 0xb000, size 128 */ 303 270 unsigned long game_io; /* usually 0xb400, size 8 */ 304 271 unsigned long mpu_io; /* usually 0xb800, size 4 */ 305 272 unsigned long opl3_io; /* usually 0xbc00, size 8 */ ··· 310 275 311 276 struct snd_timer *timer; 312 277 313 - struct snd_pcm *pcm; 314 - struct snd_azf3328_audio_stream audio_stream[2]; 278 + struct snd_pcm *pcm[3]; 279 + 280 + /* playback, recording and I2S out codecs */ 281 + struct snd_azf3328_codec_data codecs[3]; 315 282 316 283 struct snd_card *card; 317 284 struct snd_rawmidi *rmidi; 318 285 319 286 #ifdef SUPPORT_GAMEPORT 320 287 struct gameport *gameport; 321 - int axes[4]; 288 + u16 axes[4]; 322 289 #endif 323 290 324 291 struct pci_dev *pci; ··· 330 293 * If we need to add more registers here, then we might try to fold this 331 294 * into some transparent combined shadow register handling with 332 295 * CONFIG_PM register storage below, but that's slightly difficult. */ 333 - u16 shadow_reg_codec_6AH; 296 + u16 shadow_reg_ctrl_6AH; 334 297 335 298 #ifdef CONFIG_PM 336 299 /* register value containers for power management 337 300 * Note: not always full I/O range preserved (just like Win driver!) */ 338 - u16 saved_regs_codec[AZF_IO_SIZE_CODEC_PM / 2]; 301 + u16 saved_regs_ctrl[AZF_IO_SIZE_CTRL_PM / 2]; 339 302 u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2]; 340 303 u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2]; 341 304 u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2]; ··· 353 316 354 317 355 318 static int 356 - snd_azf3328_io_reg_setb(unsigned reg, u8 mask, int do_set) 319 + snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set) 357 320 { 358 321 u8 prev = inb(reg), new; 359 322 ··· 368 331 } 369 332 370 333 static inline void 371 - snd_azf3328_codec_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value) 334 + snd_azf3328_codec_outb(const struct snd_azf3328_codec_data *codec, 335 + unsigned reg, 336 + u8 value 337 + ) 372 338 { 373 - outb(value, chip->codec_io + reg); 339 + outb(value, codec->io_base + reg); 374 340 } 375 341 376 342 static inline u8 377 - snd_azf3328_codec_inb(const struct snd_azf3328 *chip, unsigned reg) 343 + snd_azf3328_codec_inb(const struct snd_azf3328_codec_data *codec, unsigned reg) 378 344 { 379 - return inb(chip->codec_io + reg); 345 + return inb(codec->io_base + reg); 380 346 } 381 347 382 348 static inline void 383 - snd_azf3328_codec_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) 349 + snd_azf3328_codec_outw(const struct snd_azf3328_codec_data *codec, 350 + unsigned reg, 351 + u16 value 352 + ) 384 353 { 385 - outw(value, chip->codec_io + reg); 354 + outw(value, codec->io_base + reg); 386 355 } 387 356 388 357 static inline u16 389 - snd_azf3328_codec_inw(const struct snd_azf3328 *chip, unsigned reg) 358 + snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg) 390 359 { 391 - return inw(chip->codec_io + reg); 360 + return inw(codec->io_base + reg); 392 361 } 393 362 394 363 static inline void 395 - snd_azf3328_codec_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value) 364 + snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec, 365 + unsigned reg, 366 + u32 value 367 + ) 396 368 { 397 - outl(value, chip->codec_io + reg); 369 + outl(value, codec->io_base + reg); 398 370 } 399 371 400 372 static inline u32 401 - snd_azf3328_codec_inl(const struct snd_azf3328 *chip, unsigned reg) 373 + snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg) 402 374 { 403 - return inl(chip->codec_io + reg); 375 + return inl(codec->io_base + reg); 376 + } 377 + 378 + static inline void 379 + snd_azf3328_ctrl_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value) 380 + { 381 + outb(value, chip->ctrl_io + reg); 382 + } 383 + 384 + static inline u8 385 + snd_azf3328_ctrl_inb(const struct snd_azf3328 *chip, unsigned reg) 386 + { 387 + return inb(chip->ctrl_io + reg); 388 + } 389 + 390 + static inline void 391 + snd_azf3328_ctrl_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) 392 + { 393 + outw(value, chip->ctrl_io + reg); 394 + } 395 + 396 + static inline void 397 + snd_azf3328_ctrl_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value) 398 + { 399 + outl(value, chip->ctrl_io + reg); 404 400 } 405 401 406 402 static inline void ··· 474 404 475 405 #define AZF_MUTE_BIT 0x80 476 406 477 - static int 407 + static bool 478 408 snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip, 479 - unsigned reg, int do_mute 409 + unsigned reg, bool do_mute 480 410 ) 481 411 { 482 412 unsigned long portbase = chip->mixer_io + reg + 1; 483 - int updated; 413 + bool updated; 484 414 485 415 /* the mute bit is on the *second* (i.e. right) register of a 486 416 * left/right channel setting */ ··· 639 569 { 640 570 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); 641 571 struct azf3328_mixer_reg reg; 642 - unsigned int oreg, val; 572 + u16 oreg, val; 643 573 644 574 snd_azf3328_dbgcallenter(); 645 575 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); ··· 670 600 { 671 601 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); 672 602 struct azf3328_mixer_reg reg; 673 - unsigned int oreg, nreg, val; 603 + u16 oreg, nreg, val; 674 604 675 605 snd_azf3328_dbgcallenter(); 676 606 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); ··· 779 709 { 780 710 struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); 781 711 struct azf3328_mixer_reg reg; 782 - unsigned int oreg, nreg, val; 712 + u16 oreg, nreg, val; 783 713 784 714 snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value); 785 715 oreg = snd_azf3328_mixer_inw(chip, reg.reg); ··· 937 867 938 868 static void 939 869 snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, 940 - unsigned reg, 870 + enum snd_azf3328_codec_type codec_type, 941 871 enum azf_freq_t bitrate, 942 872 unsigned int format_width, 943 873 unsigned int channels 944 874 ) 945 875 { 946 - u16 val = 0xff00; 947 876 unsigned long flags; 877 + const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; 878 + u16 val = 0xff00; 948 879 949 880 snd_azf3328_dbgcallenter(); 950 881 switch (bitrate) { ··· 988 917 spin_lock_irqsave(&chip->reg_lock, flags); 989 918 990 919 /* set bitrate/format */ 991 - snd_azf3328_codec_outw(chip, reg, val); 920 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); 992 921 993 922 /* changing the bitrate/format settings switches off the 994 923 * audio output with an annoying click in case of 8/16bit format change ··· 997 926 * (FIXME: yes, it works, but what exactly am I doing here?? :) 998 927 * FIXME: does this have some side effects for full-duplex 999 928 * or other dramatic side effects? */ 1000 - if (reg == IDX_IO_PLAY_SOUNDFORMAT) /* only do it for playback */ 1001 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1002 - snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | 1003 - DMA_PLAY_SOMETHING1 | 1004 - DMA_PLAY_SOMETHING2 | 929 + if (codec_type == AZF_CODEC_PLAYBACK) /* only do it for playback */ 930 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 931 + snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) | 932 + DMA_RUN_SOMETHING1 | 933 + DMA_RUN_SOMETHING2 | 1005 934 SOMETHING_ALMOST_ALWAYS_SET | 1006 935 DMA_EPILOGUE_SOMETHING | 1007 936 DMA_SOMETHING_ELSE ··· 1013 942 1014 943 static inline void 1015 944 snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip, 1016 - unsigned reg 945 + enum snd_azf3328_codec_type codec_type 1017 946 ) 1018 947 { 1019 948 /* choose lowest frequency for low power consumption. 1020 949 * While this will cause louder noise due to rather coarse frequency, 1021 950 * it should never matter since output should always 1022 951 * get disabled properly when idle anyway. */ 1023 - snd_azf3328_codec_setfmt(chip, reg, AZF_FREQ_4000, 8, 1); 952 + snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1); 1024 953 } 1025 954 1026 955 static void 1027 - snd_azf3328_codec_reg_6AH_update(struct snd_azf3328 *chip, 956 + snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip, 1028 957 unsigned bitmask, 1029 - int enable 958 + bool enable 1030 959 ) 1031 960 { 1032 961 if (enable) 1033 - chip->shadow_reg_codec_6AH &= ~bitmask; 962 + chip->shadow_reg_ctrl_6AH &= ~bitmask; 1034 963 else 1035 - chip->shadow_reg_codec_6AH |= bitmask; 964 + chip->shadow_reg_ctrl_6AH |= bitmask; 1036 965 snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n", 1037 - bitmask, enable, chip->shadow_reg_codec_6AH); 1038 - snd_azf3328_codec_outw(chip, IDX_IO_6AH, chip->shadow_reg_codec_6AH); 966 + bitmask, enable, chip->shadow_reg_ctrl_6AH); 967 + snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH); 1039 968 } 1040 969 1041 970 static inline void 1042 - snd_azf3328_codec_enable(struct snd_azf3328 *chip, int enable) 971 + snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable) 1043 972 { 1044 973 snd_azf3328_dbgplay("codec_enable %d\n", enable); 1045 974 /* no idea what exactly is being done here, but I strongly assume it's 1046 975 * PM related */ 1047 - snd_azf3328_codec_reg_6AH_update( 976 + snd_azf3328_ctrl_reg_6AH_update( 1048 977 chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable 1049 978 ); 1050 979 } 1051 980 1052 981 static void 1053 - snd_azf3328_codec_activity(struct snd_azf3328 *chip, 1054 - enum snd_azf3328_stream_index stream_type, 1055 - int enable 982 + snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip, 983 + enum snd_azf3328_codec_type codec_type, 984 + bool enable 1056 985 ) 1057 986 { 1058 - int need_change = (chip->audio_stream[stream_type].running != enable); 987 + struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; 988 + bool need_change = (codec->running != enable); 1059 989 1060 990 snd_azf3328_dbgplay( 1061 - "codec_activity: type %d, enable %d, need_change %d\n", 1062 - stream_type, enable, need_change 991 + "codec_activity: %s codec, enable %d, need_change %d\n", 992 + codec->name, enable, need_change 1063 993 ); 1064 994 if (need_change) { 1065 - enum snd_azf3328_stream_index other = 1066 - (stream_type == AZF_PLAYBACK) ? 1067 - AZF_CAPTURE : AZF_PLAYBACK; 1068 - /* small check to prevent shutting down the other party 1069 - * in case it's active */ 1070 - if ((enable) || !(chip->audio_stream[other].running)) 1071 - snd_azf3328_codec_enable(chip, enable); 995 + static const struct { 996 + enum snd_azf3328_codec_type other1; 997 + enum snd_azf3328_codec_type other2; 998 + } peer_codecs[3] = 999 + { { AZF_CODEC_CAPTURE, AZF_CODEC_I2S_OUT }, 1000 + { AZF_CODEC_PLAYBACK, AZF_CODEC_I2S_OUT }, 1001 + { AZF_CODEC_PLAYBACK, AZF_CODEC_CAPTURE } }; 1002 + bool call_function; 1003 + 1004 + if (enable) 1005 + /* if enable codec, call enable_codecs func 1006 + to enable codec supply... */ 1007 + call_function = 1; 1008 + else { 1009 + /* ...otherwise call enable_codecs func 1010 + (which globally shuts down operation of codecs) 1011 + only in case the other codecs are currently 1012 + not active either! */ 1013 + if ((!chip->codecs[peer_codecs[codec_type].other1] 1014 + .running) 1015 + && (!chip->codecs[peer_codecs[codec_type].other2] 1016 + .running)) 1017 + call_function = 1; 1018 + } 1019 + if (call_function) 1020 + snd_azf3328_ctrl_enable_codecs(chip, enable); 1072 1021 1073 1022 /* ...and adjust clock, too 1074 1023 * (reduce noise and power consumption) */ 1075 1024 if (!enable) 1076 1025 snd_azf3328_codec_setfmt_lowpower( 1077 1026 chip, 1078 - chip->audio_stream[stream_type].portbase 1079 - + IDX_IO_PLAY_SOUNDFORMAT 1027 + codec_type 1080 1028 ); 1081 1029 } 1082 - chip->audio_stream[stream_type].running = enable; 1030 + codec->running = enable; 1083 1031 } 1084 1032 1085 1033 static void 1086 - snd_azf3328_setdmaa(struct snd_azf3328 *chip, 1087 - long unsigned int addr, 1088 - unsigned int count, 1089 - unsigned int size, 1090 - enum snd_azf3328_stream_index stream_type 1034 + snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, 1035 + enum snd_azf3328_codec_type codec_type, 1036 + unsigned long addr, 1037 + unsigned int count, 1038 + unsigned int size 1091 1039 ) 1092 1040 { 1041 + const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; 1093 1042 snd_azf3328_dbgcallenter(); 1094 - if (!chip->audio_stream[stream_type].running) { 1095 - /* AZF3328 uses a two buffer pointer DMA playback approach */ 1043 + if (!codec->running) { 1044 + /* AZF3328 uses a two buffer pointer DMA transfer approach */ 1096 1045 1097 - unsigned long flags, portbase, addr_area2; 1046 + unsigned long flags; 1098 1047 1099 1048 /* width 32bit (prevent overflow): */ 1100 - unsigned long count_areas, count_tmp; 1049 + u32 addr_area2, count_areas, lengths; 1101 1050 1102 - portbase = chip->audio_stream[stream_type].portbase; 1103 1051 count_areas = size/2; 1104 1052 addr_area2 = addr+count_areas; 1105 1053 count_areas--; /* max. index */ 1106 1054 snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas); 1107 1055 1108 1056 /* build combined I/O buffer length word */ 1109 - count_tmp = count_areas; 1110 - count_areas |= (count_tmp << 16); 1057 + lengths = (count_areas << 16) | (count_areas); 1111 1058 spin_lock_irqsave(&chip->reg_lock, flags); 1112 - outl(addr, portbase + IDX_IO_PLAY_DMA_START_1); 1113 - outl(addr_area2, portbase + IDX_IO_PLAY_DMA_START_2); 1114 - outl(count_areas, portbase + IDX_IO_PLAY_DMA_LEN_1); 1059 + snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr); 1060 + snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2, 1061 + addr_area2); 1062 + snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS, 1063 + lengths); 1115 1064 spin_unlock_irqrestore(&chip->reg_lock, flags); 1116 1065 } 1117 1066 snd_azf3328_dbgcallleave(); 1118 1067 } 1119 1068 1120 1069 static int 1121 - snd_azf3328_playback_prepare(struct snd_pcm_substream *substream) 1070 + snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) 1122 1071 { 1123 1072 #if 0 1124 1073 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); ··· 1149 1058 1150 1059 snd_azf3328_dbgcallenter(); 1151 1060 #if 0 1152 - snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, 1061 + snd_azf3328_codec_setfmt(chip, AZF_CODEC_..., 1153 1062 runtime->rate, 1154 1063 snd_pcm_format_width(runtime->format), 1155 1064 runtime->channels); 1156 - snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_PLAYBACK); 1065 + snd_azf3328_codec_setdmaa(chip, AZF_CODEC_..., 1066 + runtime->dma_addr, count, size); 1157 1067 #endif 1158 1068 snd_azf3328_dbgcallleave(); 1159 1069 return 0; 1160 1070 } 1161 1071 1162 1072 static int 1163 - snd_azf3328_capture_prepare(struct snd_pcm_substream *substream) 1164 - { 1165 - #if 0 1166 - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1167 - struct snd_pcm_runtime *runtime = substream->runtime; 1168 - unsigned int size = snd_pcm_lib_buffer_bytes(substream); 1169 - unsigned int count = snd_pcm_lib_period_bytes(substream); 1170 - #endif 1171 - 1172 - snd_azf3328_dbgcallenter(); 1173 - #if 0 1174 - snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, 1175 - runtime->rate, 1176 - snd_pcm_format_width(runtime->format), 1177 - runtime->channels); 1178 - snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_CAPTURE); 1179 - #endif 1180 - snd_azf3328_dbgcallleave(); 1181 - return 0; 1182 - } 1183 - 1184 - static int 1185 - snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) 1073 + snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, 1074 + struct snd_pcm_substream *substream, int cmd) 1186 1075 { 1187 1076 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1077 + const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; 1188 1078 struct snd_pcm_runtime *runtime = substream->runtime; 1189 1079 int result = 0; 1190 - unsigned int status1; 1191 - int previously_muted; 1080 + u16 flags1; 1081 + bool previously_muted = 0; 1082 + bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type); 1192 1083 1193 - snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd); 1084 + snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd); 1194 1085 1195 1086 switch (cmd) { 1196 1087 case SNDRV_PCM_TRIGGER_START: 1197 - snd_azf3328_dbgplay("START PLAYBACK\n"); 1088 + snd_azf3328_dbgplay("START %s\n", codec->name); 1198 1089 1199 - /* mute WaveOut (avoid clicking during setup) */ 1200 - previously_muted = 1201 - snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 1090 + if (is_playback_codec) { 1091 + /* mute WaveOut (avoid clicking during setup) */ 1092 + previously_muted = 1093 + snd_azf3328_mixer_set_mute( 1094 + chip, IDX_MIXER_WAVEOUT, 1 1095 + ); 1096 + } 1202 1097 1203 - snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, 1098 + snd_azf3328_codec_setfmt(chip, codec_type, 1204 1099 runtime->rate, 1205 1100 snd_pcm_format_width(runtime->format), 1206 1101 runtime->channels); 1207 1102 1208 1103 spin_lock(&chip->reg_lock); 1209 1104 /* first, remember current value: */ 1210 - status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); 1105 + flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); 1211 1106 1212 - /* stop playback */ 1213 - status1 &= ~DMA_RESUME; 1214 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1107 + /* stop transfer */ 1108 + flags1 &= ~DMA_RESUME; 1109 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); 1215 1110 1216 1111 /* FIXME: clear interrupts or what??? */ 1217 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff); 1112 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); 1218 1113 spin_unlock(&chip->reg_lock); 1219 1114 1220 - snd_azf3328_setdmaa(chip, runtime->dma_addr, 1115 + snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr, 1221 1116 snd_pcm_lib_period_bytes(substream), 1222 - snd_pcm_lib_buffer_bytes(substream), 1223 - AZF_PLAYBACK); 1117 + snd_pcm_lib_buffer_bytes(substream) 1118 + ); 1224 1119 1225 1120 spin_lock(&chip->reg_lock); 1226 1121 #ifdef WIN9X 1227 1122 /* FIXME: enable playback/recording??? */ 1228 - status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; 1229 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1123 + flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; 1124 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); 1230 1125 1231 - /* start playback again */ 1126 + /* start transfer again */ 1232 1127 /* FIXME: what is this value (0x0010)??? */ 1233 - status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; 1234 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1128 + flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; 1129 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); 1235 1130 #else /* NT4 */ 1236 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1131 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1237 1132 0x0000); 1238 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1239 - DMA_PLAY_SOMETHING1); 1240 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1241 - DMA_PLAY_SOMETHING1 | 1242 - DMA_PLAY_SOMETHING2); 1243 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1133 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1134 + DMA_RUN_SOMETHING1); 1135 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1136 + DMA_RUN_SOMETHING1 | 1137 + DMA_RUN_SOMETHING2); 1138 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1244 1139 DMA_RESUME | 1245 1140 SOMETHING_ALMOST_ALWAYS_SET | 1246 1141 DMA_EPILOGUE_SOMETHING | 1247 1142 DMA_SOMETHING_ELSE); 1248 1143 #endif 1249 1144 spin_unlock(&chip->reg_lock); 1250 - snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 1); 1145 + snd_azf3328_ctrl_codec_activity(chip, codec_type, 1); 1251 1146 1252 - /* now unmute WaveOut */ 1253 - if (!previously_muted) 1254 - snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); 1147 + if (is_playback_codec) { 1148 + /* now unmute WaveOut */ 1149 + if (!previously_muted) 1150 + snd_azf3328_mixer_set_mute( 1151 + chip, IDX_MIXER_WAVEOUT, 0 1152 + ); 1153 + } 1255 1154 1256 - snd_azf3328_dbgplay("STARTED PLAYBACK\n"); 1155 + snd_azf3328_dbgplay("STARTED %s\n", codec->name); 1257 1156 break; 1258 1157 case SNDRV_PCM_TRIGGER_RESUME: 1259 - snd_azf3328_dbgplay("RESUME PLAYBACK\n"); 1260 - /* resume playback if we were active */ 1158 + snd_azf3328_dbgplay("RESUME %s\n", codec->name); 1159 + /* resume codec if we were active */ 1261 1160 spin_lock(&chip->reg_lock); 1262 - if (chip->audio_stream[AZF_PLAYBACK].running) 1263 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1264 - snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME); 1161 + if (codec->running) 1162 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1163 + snd_azf3328_codec_inw( 1164 + codec, IDX_IO_CODEC_DMA_FLAGS 1165 + ) | DMA_RESUME 1166 + ); 1265 1167 spin_unlock(&chip->reg_lock); 1266 1168 break; 1267 1169 case SNDRV_PCM_TRIGGER_STOP: 1268 - snd_azf3328_dbgplay("STOP PLAYBACK\n"); 1170 + snd_azf3328_dbgplay("STOP %s\n", codec->name); 1269 1171 1270 - /* mute WaveOut (avoid clicking during setup) */ 1271 - previously_muted = 1272 - snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 1172 + if (is_playback_codec) { 1173 + /* mute WaveOut (avoid clicking during setup) */ 1174 + previously_muted = 1175 + snd_azf3328_mixer_set_mute( 1176 + chip, IDX_MIXER_WAVEOUT, 1 1177 + ); 1178 + } 1273 1179 1274 1180 spin_lock(&chip->reg_lock); 1275 1181 /* first, remember current value: */ 1276 - status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); 1182 + flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); 1277 1183 1278 - /* stop playback */ 1279 - status1 &= ~DMA_RESUME; 1280 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1184 + /* stop transfer */ 1185 + flags1 &= ~DMA_RESUME; 1186 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); 1281 1187 1282 1188 /* hmm, is this really required? we're resetting the same bit 1283 1189 * immediately thereafter... */ 1284 - status1 |= DMA_PLAY_SOMETHING1; 1285 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1190 + flags1 |= DMA_RUN_SOMETHING1; 1191 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); 1286 1192 1287 - status1 &= ~DMA_PLAY_SOMETHING1; 1288 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); 1193 + flags1 &= ~DMA_RUN_SOMETHING1; 1194 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); 1289 1195 spin_unlock(&chip->reg_lock); 1290 - snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0); 1196 + snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); 1291 1197 1292 - /* now unmute WaveOut */ 1293 - if (!previously_muted) 1294 - snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); 1198 + if (is_playback_codec) { 1199 + /* now unmute WaveOut */ 1200 + if (!previously_muted) 1201 + snd_azf3328_mixer_set_mute( 1202 + chip, IDX_MIXER_WAVEOUT, 0 1203 + ); 1204 + } 1295 1205 1296 - snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); 1206 + snd_azf3328_dbgplay("STOPPED %s\n", codec->name); 1297 1207 break; 1298 1208 case SNDRV_PCM_TRIGGER_SUSPEND: 1299 - snd_azf3328_dbgplay("SUSPEND PLAYBACK\n"); 1300 - /* make sure playback is stopped */ 1301 - snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 1302 - snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME); 1209 + snd_azf3328_dbgplay("SUSPEND %s\n", codec->name); 1210 + /* make sure codec is stopped */ 1211 + snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, 1212 + snd_azf3328_codec_inw( 1213 + codec, IDX_IO_CODEC_DMA_FLAGS 1214 + ) & ~DMA_RESUME 1215 + ); 1303 1216 break; 1304 1217 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1305 1218 snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); ··· 1320 1225 return result; 1321 1226 } 1322 1227 1323 - /* this is just analogous to playback; I'm not quite sure whether recording 1324 - * should actually be triggered like that */ 1325 1228 static int 1326 - snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) 1229 + snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd) 1327 1230 { 1328 - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1329 - struct snd_pcm_runtime *runtime = substream->runtime; 1330 - int result = 0; 1331 - unsigned int status1; 1231 + return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd); 1232 + } 1332 1233 1333 - snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd); 1234 + static int 1235 + snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd) 1236 + { 1237 + return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd); 1238 + } 1334 1239 1335 - switch (cmd) { 1336 - case SNDRV_PCM_TRIGGER_START: 1337 - 1338 - snd_azf3328_dbgplay("START CAPTURE\n"); 1339 - 1340 - snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, 1341 - runtime->rate, 1342 - snd_pcm_format_width(runtime->format), 1343 - runtime->channels); 1344 - 1345 - spin_lock(&chip->reg_lock); 1346 - /* first, remember current value: */ 1347 - status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); 1348 - 1349 - /* stop recording */ 1350 - status1 &= ~DMA_RESUME; 1351 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1352 - 1353 - /* FIXME: clear interrupts or what??? */ 1354 - snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff); 1355 - spin_unlock(&chip->reg_lock); 1356 - 1357 - snd_azf3328_setdmaa(chip, runtime->dma_addr, 1358 - snd_pcm_lib_period_bytes(substream), 1359 - snd_pcm_lib_buffer_bytes(substream), 1360 - AZF_CAPTURE); 1361 - 1362 - spin_lock(&chip->reg_lock); 1363 - #ifdef WIN9X 1364 - /* FIXME: enable playback/recording??? */ 1365 - status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; 1366 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1367 - 1368 - /* start capture again */ 1369 - /* FIXME: what is this value (0x0010)??? */ 1370 - status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; 1371 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1372 - #else 1373 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 1374 - 0x0000); 1375 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 1376 - DMA_PLAY_SOMETHING1); 1377 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 1378 - DMA_PLAY_SOMETHING1 | 1379 - DMA_PLAY_SOMETHING2); 1380 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 1381 - DMA_RESUME | 1382 - SOMETHING_ALMOST_ALWAYS_SET | 1383 - DMA_EPILOGUE_SOMETHING | 1384 - DMA_SOMETHING_ELSE); 1385 - #endif 1386 - spin_unlock(&chip->reg_lock); 1387 - snd_azf3328_codec_activity(chip, AZF_CAPTURE, 1); 1388 - 1389 - snd_azf3328_dbgplay("STARTED CAPTURE\n"); 1390 - break; 1391 - case SNDRV_PCM_TRIGGER_RESUME: 1392 - snd_azf3328_dbgplay("RESUME CAPTURE\n"); 1393 - /* resume recording if we were active */ 1394 - spin_lock(&chip->reg_lock); 1395 - if (chip->audio_stream[AZF_CAPTURE].running) 1396 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 1397 - snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME); 1398 - spin_unlock(&chip->reg_lock); 1399 - break; 1400 - case SNDRV_PCM_TRIGGER_STOP: 1401 - snd_azf3328_dbgplay("STOP CAPTURE\n"); 1402 - 1403 - spin_lock(&chip->reg_lock); 1404 - /* first, remember current value: */ 1405 - status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); 1406 - 1407 - /* stop recording */ 1408 - status1 &= ~DMA_RESUME; 1409 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1410 - 1411 - status1 |= DMA_PLAY_SOMETHING1; 1412 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1413 - 1414 - status1 &= ~DMA_PLAY_SOMETHING1; 1415 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); 1416 - spin_unlock(&chip->reg_lock); 1417 - snd_azf3328_codec_activity(chip, AZF_CAPTURE, 0); 1418 - 1419 - snd_azf3328_dbgplay("STOPPED CAPTURE\n"); 1420 - break; 1421 - case SNDRV_PCM_TRIGGER_SUSPEND: 1422 - snd_azf3328_dbgplay("SUSPEND CAPTURE\n"); 1423 - /* make sure recording is stopped */ 1424 - snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, 1425 - snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME); 1426 - break; 1427 - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1428 - snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); 1429 - break; 1430 - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1431 - snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); 1432 - break; 1433 - default: 1434 - printk(KERN_ERR "FIXME: unknown trigger mode!\n"); 1435 - return -EINVAL; 1436 - } 1437 - 1438 - snd_azf3328_dbgcallleave(); 1439 - return result; 1240 + static int 1241 + snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd) 1242 + { 1243 + return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd); 1440 1244 } 1441 1245 1442 1246 static snd_pcm_uframes_t 1443 - snd_azf3328_playback_pointer(struct snd_pcm_substream *substream) 1247 + snd_azf3328_codec_pointer(struct snd_pcm_substream *substream, 1248 + enum snd_azf3328_codec_type codec_type 1249 + ) 1444 1250 { 1445 - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1251 + const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1252 + const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; 1446 1253 unsigned long bufptr, result; 1447 1254 snd_pcm_uframes_t frmres; 1448 1255 1449 1256 #ifdef QUERY_HARDWARE 1450 - bufptr = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_START_1); 1257 + bufptr = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1); 1451 1258 #else 1452 1259 bufptr = substream->runtime->dma_addr; 1453 1260 #endif 1454 - result = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_CURRPOS); 1261 + result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS); 1455 1262 1456 1263 /* calculate offset */ 1457 1264 result -= bufptr; 1458 1265 frmres = bytes_to_frames( substream->runtime, result); 1459 - snd_azf3328_dbgplay("PLAY @ 0x%8lx, frames %8ld\n", result, frmres); 1266 + snd_azf3328_dbgplay("%s @ 0x%8lx, frames %8ld\n", 1267 + codec->name, result, frmres); 1460 1268 return frmres; 1461 1269 } 1462 1270 1463 1271 static snd_pcm_uframes_t 1464 - snd_azf3328_capture_pointer(struct snd_pcm_substream *substream) 1272 + snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream) 1465 1273 { 1466 - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1467 - unsigned long bufptr, result; 1468 - snd_pcm_uframes_t frmres; 1274 + return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK); 1275 + } 1469 1276 1470 - #ifdef QUERY_HARDWARE 1471 - bufptr = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_START_1); 1472 - #else 1473 - bufptr = substream->runtime->dma_addr; 1474 - #endif 1475 - result = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_CURRPOS); 1277 + static snd_pcm_uframes_t 1278 + snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream) 1279 + { 1280 + return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE); 1281 + } 1476 1282 1477 - /* calculate offset */ 1478 - result -= bufptr; 1479 - frmres = bytes_to_frames( substream->runtime, result); 1480 - snd_azf3328_dbgplay("REC @ 0x%8lx, frames %8ld\n", result, frmres); 1481 - return frmres; 1283 + static snd_pcm_uframes_t 1284 + snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream) 1285 + { 1286 + return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT); 1482 1287 } 1483 1288 1484 1289 /******************************************************************/ 1485 1290 1486 1291 #ifdef SUPPORT_GAMEPORT 1487 1292 static inline void 1488 - snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, int enable) 1293 + snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, 1294 + bool enable 1295 + ) 1489 1296 { 1490 1297 snd_azf3328_io_reg_setb( 1491 1298 chip->game_io+IDX_GAME_HWCONFIG, ··· 1397 1400 } 1398 1401 1399 1402 static inline void 1400 - snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, int enable) 1403 + snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, 1404 + bool enable 1405 + ) 1401 1406 { 1402 1407 snd_azf3328_io_reg_setb( 1403 1408 chip->game_io+IDX_GAME_HWCONFIG, ··· 1408 1409 ); 1409 1410 } 1410 1411 1411 - static inline void 1412 - snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, int enable) 1412 + static void 1413 + snd_azf3328_gameport_set_counter_frequency(struct snd_azf3328 *chip, 1414 + unsigned int freq_cfg 1415 + ) 1413 1416 { 1414 - snd_azf3328_codec_reg_6AH_update( 1417 + snd_azf3328_io_reg_setb( 1418 + chip->game_io+IDX_GAME_HWCONFIG, 1419 + 0x02, 1420 + (freq_cfg & 1) != 0 1421 + ); 1422 + snd_azf3328_io_reg_setb( 1423 + chip->game_io+IDX_GAME_HWCONFIG, 1424 + 0x04, 1425 + (freq_cfg & 2) != 0 1426 + ); 1427 + } 1428 + 1429 + static inline void 1430 + snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, bool enable) 1431 + { 1432 + snd_azf3328_ctrl_reg_6AH_update( 1415 1433 chip, IO_6A_SOMETHING2_GAMEPORT, enable 1416 1434 ); 1417 1435 } ··· 1463 1447 break; 1464 1448 } 1465 1449 1450 + snd_azf3328_gameport_set_counter_frequency(chip, 1451 + GAME_HWCFG_ADC_COUNTER_FREQ_STD); 1466 1452 snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0)); 1467 1453 1468 1454 return res; ··· 1476 1458 struct snd_azf3328 *chip = gameport_get_port_data(gameport); 1477 1459 1478 1460 snd_azf3328_dbggame("gameport_close\n"); 1461 + snd_azf3328_gameport_set_counter_frequency(chip, 1462 + GAME_HWCFG_ADC_COUNTER_FREQ_1_200); 1479 1463 snd_azf3328_gameport_axis_circuit_enable(chip, 0); 1480 1464 } 1481 1465 ··· 1511 1491 1512 1492 val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG); 1513 1493 if (val & GAME_AXES_SAMPLING_READY) { 1514 - for (i = 0; i < 4; ++i) { 1494 + for (i = 0; i < ARRAY_SIZE(chip->axes); ++i) { 1515 1495 /* configure the axis to read */ 1516 1496 val = (i << 4) | 0x0f; 1517 1497 snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val); ··· 1534 1514 snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff); 1535 1515 spin_unlock_irqrestore(&chip->reg_lock, flags); 1536 1516 1537 - for (i = 0; i < 4; i++) { 1517 + for (i = 0; i < ARRAY_SIZE(chip->axes); i++) { 1538 1518 axes[i] = chip->axes[i]; 1539 1519 if (axes[i] == 0xffff) 1540 1520 axes[i] = -1; ··· 1572 1552 /* DISABLE legacy address: we don't need it! */ 1573 1553 snd_azf3328_gameport_legacy_address_enable(chip, 0); 1574 1554 1555 + snd_azf3328_gameport_set_counter_frequency(chip, 1556 + GAME_HWCFG_ADC_COUNTER_FREQ_1_200); 1575 1557 snd_azf3328_gameport_axis_circuit_enable(chip, 0); 1576 1558 1577 1559 gameport_register_port(chip->gameport); ··· 1613 1591 ); 1614 1592 } 1615 1593 1594 + static inline void 1595 + snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status) 1596 + { 1597 + u8 which; 1598 + enum snd_azf3328_codec_type codec_type; 1599 + const struct snd_azf3328_codec_data *codec; 1600 + 1601 + for (codec_type = AZF_CODEC_PLAYBACK; 1602 + codec_type <= AZF_CODEC_I2S_OUT; 1603 + ++codec_type) { 1604 + 1605 + /* skip codec if there's no interrupt for it */ 1606 + if (!(status & (1 << codec_type))) 1607 + continue; 1608 + 1609 + codec = &chip->codecs[codec_type]; 1610 + 1611 + spin_lock(&chip->reg_lock); 1612 + which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); 1613 + /* ack all IRQ types immediately */ 1614 + snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); 1615 + spin_unlock(&chip->reg_lock); 1616 + 1617 + if ((chip->pcm[codec_type]) 1618 + && (chip->codecs[codec_type].substream)) { 1619 + snd_pcm_period_elapsed( 1620 + chip->codecs[codec_type].substream 1621 + ); 1622 + snd_azf3328_dbgplay("%s period done (#%x), @ %x\n", 1623 + codec->name, 1624 + which, 1625 + snd_azf3328_codec_inl( 1626 + codec, IDX_IO_CODEC_DMA_CURRPOS 1627 + ) 1628 + ); 1629 + } else 1630 + printk(KERN_WARNING "azt3328: irq handler problem!\n"); 1631 + if (which & IRQ_SOMETHING) 1632 + snd_azf3328_irq_log_unknown_type(which); 1633 + } 1634 + } 1635 + 1616 1636 static irqreturn_t 1617 1637 snd_azf3328_interrupt(int irq, void *dev_id) 1618 1638 { 1619 1639 struct snd_azf3328 *chip = dev_id; 1620 - u8 status, which; 1640 + u8 status; 1621 1641 #if DEBUG_PLAY_REC 1622 1642 static unsigned long irq_count; 1623 1643 #endif 1624 1644 1625 - status = snd_azf3328_codec_inb(chip, IDX_IO_IRQSTATUS); 1645 + status = snd_azf3328_ctrl_inb(chip, IDX_IO_IRQSTATUS); 1626 1646 1627 1647 /* fast path out, to ease interrupt sharing */ 1628 1648 if (!(status & 1629 - (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER) 1649 + (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT 1650 + |IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER) 1630 1651 )) 1631 1652 return IRQ_NONE; /* must be interrupt for another device */ 1632 1653 1633 1654 snd_azf3328_dbgplay( 1634 - "irq_count %ld! IDX_IO_PLAY_FLAGS %04x, " 1635 - "IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n", 1655 + "irq_count %ld! IDX_IO_IRQSTATUS %04x\n", 1636 1656 irq_count++ /* debug-only */, 1637 - snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS), 1638 - snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), 1639 1657 status 1640 1658 ); 1641 1659 ··· 1688 1626 snd_timer_interrupt(chip->timer, chip->timer->sticks); 1689 1627 /* ACK timer */ 1690 1628 spin_lock(&chip->reg_lock); 1691 - snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); 1629 + snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); 1692 1630 spin_unlock(&chip->reg_lock); 1693 1631 snd_azf3328_dbgplay("azt3328: timer IRQ\n"); 1694 1632 } 1695 - if (status & IRQ_PLAYBACK) { 1696 - spin_lock(&chip->reg_lock); 1697 - which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); 1698 - /* ack all IRQ types immediately */ 1699 - snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); 1700 - spin_unlock(&chip->reg_lock); 1701 1633 1702 - if (chip->pcm && chip->audio_stream[AZF_PLAYBACK].substream) { 1703 - snd_pcm_period_elapsed( 1704 - chip->audio_stream[AZF_PLAYBACK].substream 1705 - ); 1706 - snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", 1707 - which, 1708 - snd_azf3328_codec_inl( 1709 - chip, IDX_IO_PLAY_DMA_CURRPOS 1710 - ) 1711 - ); 1712 - } else 1713 - printk(KERN_WARNING "azt3328: irq handler problem!\n"); 1714 - if (which & IRQ_PLAY_SOMETHING) 1715 - snd_azf3328_irq_log_unknown_type(which); 1716 - } 1717 - if (status & IRQ_RECORDING) { 1718 - spin_lock(&chip->reg_lock); 1719 - which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); 1720 - /* ack all IRQ types immediately */ 1721 - snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); 1722 - spin_unlock(&chip->reg_lock); 1634 + if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) 1635 + snd_azf3328_codec_interrupt(chip, status); 1723 1636 1724 - if (chip->pcm && chip->audio_stream[AZF_CAPTURE].substream) { 1725 - snd_pcm_period_elapsed( 1726 - chip->audio_stream[AZF_CAPTURE].substream 1727 - ); 1728 - snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", 1729 - which, 1730 - snd_azf3328_codec_inl( 1731 - chip, IDX_IO_REC_DMA_CURRPOS 1732 - ) 1733 - ); 1734 - } else 1735 - printk(KERN_WARNING "azt3328: irq handler problem!\n"); 1736 - if (which & IRQ_REC_SOMETHING) 1737 - snd_azf3328_irq_log_unknown_type(which); 1738 - } 1739 1637 if (status & IRQ_GAMEPORT) 1740 1638 snd_azf3328_gameport_interrupt(chip); 1639 + 1741 1640 /* MPU401 has less critical IRQ requirements 1742 1641 * than timer and playback/recording, right? */ 1743 1642 if (status & IRQ_MPU401) { 1744 1643 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); 1745 1644 1746 1645 /* hmm, do we have to ack the IRQ here somehow? 1747 - * If so, then I don't know how... */ 1646 + * If so, then I don't know how yet... */ 1748 1647 snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n"); 1749 1648 } 1750 1649 return IRQ_HANDLED; ··· 1713 1690 1714 1691 /*****************************************************************/ 1715 1692 1716 - static const struct snd_pcm_hardware snd_azf3328_playback = 1693 + /* as long as we think we have identical snd_pcm_hardware parameters 1694 + for playback, capture and i2s out, we can use the same physical struct 1695 + since the struct is simply being copied into a member. 1696 + */ 1697 + static const struct snd_pcm_hardware snd_azf3328_hardware = 1717 1698 { 1718 1699 /* FIXME!! Correct? */ 1719 1700 .info = SNDRV_PCM_INFO_MMAP | ··· 1742 1715 /* FIXME: maybe that card actually has a FIFO? 1743 1716 * Hmm, it seems newer revisions do have one, but we still don't know 1744 1717 * its size... */ 1745 - .fifo_size = 0, 1746 - }; 1747 - 1748 - static const struct snd_pcm_hardware snd_azf3328_capture = 1749 - { 1750 - /* FIXME */ 1751 - .info = SNDRV_PCM_INFO_MMAP | 1752 - SNDRV_PCM_INFO_INTERLEAVED | 1753 - SNDRV_PCM_INFO_MMAP_VALID, 1754 - .formats = SNDRV_PCM_FMTBIT_S8 | 1755 - SNDRV_PCM_FMTBIT_U8 | 1756 - SNDRV_PCM_FMTBIT_S16_LE | 1757 - SNDRV_PCM_FMTBIT_U16_LE, 1758 - .rates = SNDRV_PCM_RATE_5512 | 1759 - SNDRV_PCM_RATE_8000_48000 | 1760 - SNDRV_PCM_RATE_KNOT, 1761 - .rate_min = AZF_FREQ_4000, 1762 - .rate_max = AZF_FREQ_66200, 1763 - .channels_min = 1, 1764 - .channels_max = 2, 1765 - .buffer_bytes_max = 65536, 1766 - .period_bytes_min = 64, 1767 - .period_bytes_max = 65536, 1768 - .periods_min = 1, 1769 - .periods_max = 1024, 1770 1718 .fifo_size = 0, 1771 1719 }; 1772 1720 ··· 1772 1770 /*****************************************************************/ 1773 1771 1774 1772 static int 1775 - snd_azf3328_playback_open(struct snd_pcm_substream *substream) 1773 + snd_azf3328_pcm_open(struct snd_pcm_substream *substream, 1774 + enum snd_azf3328_codec_type codec_type 1775 + ) 1776 1776 { 1777 1777 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1778 1778 struct snd_pcm_runtime *runtime = substream->runtime; 1779 1779 1780 1780 snd_azf3328_dbgcallenter(); 1781 - chip->audio_stream[AZF_PLAYBACK].substream = substream; 1782 - runtime->hw = snd_azf3328_playback; 1781 + chip->codecs[codec_type].substream = substream; 1782 + 1783 + /* same parameters for all our codecs - at least we think so... */ 1784 + runtime->hw = snd_azf3328_hardware; 1785 + 1783 1786 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 1784 1787 &snd_azf3328_hw_constraints_rates); 1785 1788 snd_azf3328_dbgcallleave(); ··· 1792 1785 } 1793 1786 1794 1787 static int 1788 + snd_azf3328_playback_open(struct snd_pcm_substream *substream) 1789 + { 1790 + return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK); 1791 + } 1792 + 1793 + static int 1795 1794 snd_azf3328_capture_open(struct snd_pcm_substream *substream) 1796 1795 { 1796 + return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE); 1797 + } 1798 + 1799 + static int 1800 + snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream) 1801 + { 1802 + return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT); 1803 + } 1804 + 1805 + static int 1806 + snd_azf3328_pcm_close(struct snd_pcm_substream *substream, 1807 + enum snd_azf3328_codec_type codec_type 1808 + ) 1809 + { 1797 1810 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1798 - struct snd_pcm_runtime *runtime = substream->runtime; 1799 1811 1800 1812 snd_azf3328_dbgcallenter(); 1801 - chip->audio_stream[AZF_CAPTURE].substream = substream; 1802 - runtime->hw = snd_azf3328_capture; 1803 - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 1804 - &snd_azf3328_hw_constraints_rates); 1813 + chip->codecs[codec_type].substream = NULL; 1805 1814 snd_azf3328_dbgcallleave(); 1806 1815 return 0; 1807 1816 } ··· 1825 1802 static int 1826 1803 snd_azf3328_playback_close(struct snd_pcm_substream *substream) 1827 1804 { 1828 - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1829 - 1830 - snd_azf3328_dbgcallenter(); 1831 - chip->audio_stream[AZF_PLAYBACK].substream = NULL; 1832 - snd_azf3328_dbgcallleave(); 1833 - return 0; 1805 + return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK); 1834 1806 } 1835 1807 1836 1808 static int 1837 1809 snd_azf3328_capture_close(struct snd_pcm_substream *substream) 1838 1810 { 1839 - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); 1811 + return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE); 1812 + } 1840 1813 1841 - snd_azf3328_dbgcallenter(); 1842 - chip->audio_stream[AZF_CAPTURE].substream = NULL; 1843 - snd_azf3328_dbgcallleave(); 1844 - return 0; 1814 + static int 1815 + snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream) 1816 + { 1817 + return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT); 1845 1818 } 1846 1819 1847 1820 /******************************************************************/ ··· 1848 1829 .ioctl = snd_pcm_lib_ioctl, 1849 1830 .hw_params = snd_azf3328_hw_params, 1850 1831 .hw_free = snd_azf3328_hw_free, 1851 - .prepare = snd_azf3328_playback_prepare, 1852 - .trigger = snd_azf3328_playback_trigger, 1853 - .pointer = snd_azf3328_playback_pointer 1832 + .prepare = snd_azf3328_codec_prepare, 1833 + .trigger = snd_azf3328_codec_playback_trigger, 1834 + .pointer = snd_azf3328_codec_playback_pointer 1854 1835 }; 1855 1836 1856 1837 static struct snd_pcm_ops snd_azf3328_capture_ops = { ··· 1859 1840 .ioctl = snd_pcm_lib_ioctl, 1860 1841 .hw_params = snd_azf3328_hw_params, 1861 1842 .hw_free = snd_azf3328_hw_free, 1862 - .prepare = snd_azf3328_capture_prepare, 1863 - .trigger = snd_azf3328_capture_trigger, 1864 - .pointer = snd_azf3328_capture_pointer 1843 + .prepare = snd_azf3328_codec_prepare, 1844 + .trigger = snd_azf3328_codec_capture_trigger, 1845 + .pointer = snd_azf3328_codec_capture_pointer 1846 + }; 1847 + 1848 + static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { 1849 + .open = snd_azf3328_i2s_out_open, 1850 + .close = snd_azf3328_i2s_out_close, 1851 + .ioctl = snd_pcm_lib_ioctl, 1852 + .hw_params = snd_azf3328_hw_params, 1853 + .hw_free = snd_azf3328_hw_free, 1854 + .prepare = snd_azf3328_codec_prepare, 1855 + .trigger = snd_azf3328_codec_i2s_out_trigger, 1856 + .pointer = snd_azf3328_codec_i2s_out_pointer 1865 1857 }; 1866 1858 1867 1859 static int __devinit 1868 - snd_azf3328_pcm(struct snd_azf3328 *chip, int device) 1860 + snd_azf3328_pcm(struct snd_azf3328 *chip) 1869 1861 { 1862 + enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */ 1863 + 1870 1864 struct snd_pcm *pcm; 1871 1865 int err; 1872 1866 1873 1867 snd_azf3328_dbgcallenter(); 1874 - if ((err = snd_pcm_new(chip->card, "AZF3328 DSP", device, 1, 1, &pcm)) < 0) 1868 + 1869 + err = snd_pcm_new(chip->card, "AZF3328 DSP", AZF_PCMDEV_STD, 1870 + 1, 1, &pcm); 1871 + if (err < 0) 1875 1872 return err; 1876 - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_azf3328_playback_ops); 1877 - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_azf3328_capture_ops); 1873 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1874 + &snd_azf3328_playback_ops); 1875 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 1876 + &snd_azf3328_capture_ops); 1878 1877 1879 1878 pcm->private_data = chip; 1880 1879 pcm->info_flags = 0; 1881 1880 strcpy(pcm->name, chip->card->shortname); 1882 - chip->pcm = pcm; 1881 + /* same pcm object for playback/capture (see snd_pcm_new() above) */ 1882 + chip->pcm[AZF_CODEC_PLAYBACK] = pcm; 1883 + chip->pcm[AZF_CODEC_CAPTURE] = pcm; 1883 1884 1884 1885 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 1885 - snd_dma_pci_data(chip->pci), 64*1024, 64*1024); 1886 + snd_dma_pci_data(chip->pci), 1887 + 64*1024, 64*1024); 1888 + 1889 + err = snd_pcm_new(chip->card, "AZF3328 I2S OUT", AZF_PCMDEV_I2S_OUT, 1890 + 1, 0, &pcm); 1891 + if (err < 0) 1892 + return err; 1893 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1894 + &snd_azf3328_i2s_out_ops); 1895 + 1896 + pcm->private_data = chip; 1897 + pcm->info_flags = 0; 1898 + strcpy(pcm->name, chip->card->shortname); 1899 + chip->pcm[AZF_CODEC_I2S_OUT] = pcm; 1900 + 1901 + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 1902 + snd_dma_pci_data(chip->pci), 1903 + 64*1024, 64*1024); 1886 1904 1887 1905 snd_azf3328_dbgcallleave(); 1888 1906 return 0; ··· 1958 1902 snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay); 1959 1903 delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; 1960 1904 spin_lock_irqsave(&chip->reg_lock, flags); 1961 - snd_azf3328_codec_outl(chip, IDX_IO_TIMER_VALUE, delay); 1905 + snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay); 1962 1906 spin_unlock_irqrestore(&chip->reg_lock, flags); 1963 1907 snd_azf3328_dbgcallleave(); 1964 1908 return 0; ··· 1975 1919 spin_lock_irqsave(&chip->reg_lock, flags); 1976 1920 /* disable timer countdown and interrupt */ 1977 1921 /* FIXME: should we write TIMER_IRQ_ACK here? */ 1978 - snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); 1922 + snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); 1979 1923 spin_unlock_irqrestore(&chip->reg_lock, flags); 1980 1924 snd_azf3328_dbgcallleave(); 1981 1925 return 0; ··· 2104 2048 u16 tmp; 2105 2049 2106 2050 snd_azf3328_dbgmisc( 2107 - "codec_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, " 2051 + "ctrl_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, " 2108 2052 "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n", 2109 - chip->codec_io, chip->game_io, chip->mpu_io, 2053 + chip->ctrl_io, chip->game_io, chip->mpu_io, 2110 2054 chip->opl3_io, chip->mixer_io, chip->irq 2111 2055 ); 2112 2056 ··· 2139 2083 inb(0x38c + tmp) 2140 2084 ); 2141 2085 2142 - for (tmp = 0; tmp < AZF_IO_SIZE_CODEC; tmp += 2) 2143 - snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n", 2144 - tmp, snd_azf3328_codec_inw(chip, tmp) 2086 + for (tmp = 0; tmp < AZF_IO_SIZE_CTRL; tmp += 2) 2087 + snd_azf3328_dbgmisc("ctrl 0x%02x: 0x%04x\n", 2088 + tmp, snd_azf3328_ctrl_inw(chip, tmp) 2145 2089 ); 2146 2090 2147 2091 for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2) ··· 2162 2106 static struct snd_device_ops ops = { 2163 2107 .dev_free = snd_azf3328_dev_free, 2164 2108 }; 2165 - u16 tmp; 2109 + u8 dma_init; 2110 + enum snd_azf3328_codec_type codec_type; 2166 2111 2167 2112 *rchip = NULL; 2168 2113 ··· 2195 2138 if (err < 0) 2196 2139 goto out_err; 2197 2140 2198 - chip->codec_io = pci_resource_start(pci, 0); 2141 + chip->ctrl_io = pci_resource_start(pci, 0); 2199 2142 chip->game_io = pci_resource_start(pci, 1); 2200 2143 chip->mpu_io = pci_resource_start(pci, 2); 2201 - chip->opl3_io = pci_resource_start(pci, 3); 2144 + chip->opl3_io = pci_resource_start(pci, 3); 2202 2145 chip->mixer_io = pci_resource_start(pci, 4); 2203 2146 2204 - chip->audio_stream[AZF_PLAYBACK].portbase = chip->codec_io + 0x00; 2205 - chip->audio_stream[AZF_CAPTURE].portbase = chip->codec_io + 0x20; 2147 + chip->codecs[AZF_CODEC_PLAYBACK].io_base = 2148 + chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK; 2149 + chip->codecs[AZF_CODEC_PLAYBACK].name = "PLAYBACK"; 2150 + chip->codecs[AZF_CODEC_CAPTURE].io_base = 2151 + chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE; 2152 + chip->codecs[AZF_CODEC_CAPTURE].name = "CAPTURE"; 2153 + chip->codecs[AZF_CODEC_I2S_OUT].io_base = 2154 + chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT; 2155 + chip->codecs[AZF_CODEC_I2S_OUT].name = "I2S_OUT"; 2206 2156 2207 2157 if (request_irq(pci->irq, snd_azf3328_interrupt, 2208 2158 IRQF_SHARED, card->shortname, chip)) { ··· 2232 2168 if (err < 0) 2233 2169 goto out_err; 2234 2170 2235 - /* shutdown codecs to save power */ 2236 - /* have snd_azf3328_codec_activity() act properly */ 2237 - chip->audio_stream[AZF_PLAYBACK].running = 1; 2238 - snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0); 2171 + /* standard codec init stuff */ 2172 + /* default DMA init value */ 2173 + dma_init = DMA_RUN_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; 2239 2174 2240 - /* standard chip init stuff */ 2241 - /* default IRQ init value */ 2242 - tmp = DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; 2175 + for (codec_type = AZF_CODEC_PLAYBACK; 2176 + codec_type <= AZF_CODEC_I2S_OUT; ++codec_type) { 2177 + struct snd_azf3328_codec_data *codec = 2178 + &chip->codecs[codec_type]; 2243 2179 2244 - spin_lock_irq(&chip->reg_lock); 2245 - snd_azf3328_codec_outb(chip, IDX_IO_PLAY_FLAGS, tmp); 2246 - snd_azf3328_codec_outb(chip, IDX_IO_REC_FLAGS, tmp); 2247 - snd_azf3328_codec_outb(chip, IDX_IO_SOMETHING_FLAGS, tmp); 2248 - spin_unlock_irq(&chip->reg_lock); 2180 + /* shutdown codecs to save power */ 2181 + /* have ...ctrl_codec_activity() act properly */ 2182 + codec->running = 1; 2183 + snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); 2184 + 2185 + spin_lock_irq(&chip->reg_lock); 2186 + snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, 2187 + dma_init); 2188 + spin_unlock_irq(&chip->reg_lock); 2189 + } 2249 2190 2250 2191 snd_card_set_dev(card, &pci->dev); 2251 2192 ··· 2313 2244 if (err < 0) 2314 2245 goto out_err; 2315 2246 2316 - err = snd_azf3328_pcm(chip, 0); 2247 + err = snd_azf3328_pcm(chip); 2317 2248 if (err < 0) 2318 2249 goto out_err; 2319 2250 ··· 2335 2266 opl3->private_data = chip; 2336 2267 2337 2268 sprintf(card->longname, "%s at 0x%lx, irq %i", 2338 - card->shortname, chip->codec_io, chip->irq); 2269 + card->shortname, chip->ctrl_io, chip->irq); 2339 2270 2340 2271 err = snd_card_register(card); 2341 2272 if (err < 0) ··· 2386 2317 2387 2318 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 2388 2319 2389 - snd_pcm_suspend_all(chip->pcm); 2320 + snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); 2321 + snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); 2390 2322 2391 2323 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) 2392 2324 chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2); ··· 2396 2326 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); 2397 2327 snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); 2398 2328 2399 - for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg) 2400 - chip->saved_regs_codec[reg] = inw(chip->codec_io + reg * 2); 2329 + for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg) 2330 + chip->saved_regs_ctrl[reg] = inw(chip->ctrl_io + reg * 2); 2401 2331 2402 2332 /* manually store the one currently relevant write-only reg, too */ 2403 - chip->saved_regs_codec[IDX_IO_6AH / 2] = chip->shadow_reg_codec_6AH; 2333 + chip->saved_regs_ctrl[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH; 2404 2334 2405 2335 for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg) 2406 2336 chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2); ··· 2419 2349 snd_azf3328_resume(struct pci_dev *pci) 2420 2350 { 2421 2351 struct snd_card *card = pci_get_drvdata(pci); 2422 - struct snd_azf3328 *chip = card->private_data; 2352 + const struct snd_azf3328 *chip = card->private_data; 2423 2353 unsigned reg; 2424 2354 2425 2355 pci_set_power_state(pci, PCI_D0); ··· 2440 2370 outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2); 2441 2371 for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) 2442 2372 outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2); 2443 - for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg) 2444 - outw(chip->saved_regs_codec[reg], chip->codec_io + reg * 2); 2373 + for (reg = 0; reg < AZF_IO_SIZE_CTRL_PM / 2; ++reg) 2374 + outw(chip->saved_regs_ctrl[reg], chip->ctrl_io + reg * 2); 2445 2375 2446 2376 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 2447 2377 return 0;
+40 -47
sound/pci/azt3328.h
··· 6 6 7 7 /*** main I/O area port indices ***/ 8 8 /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ 9 - #define AZF_IO_SIZE_CODEC 0x80 10 - #define AZF_IO_SIZE_CODEC_PM 0x70 9 + #define AZF_IO_SIZE_CTRL 0x80 10 + #define AZF_IO_SIZE_CTRL_PM 0x70 11 11 12 - /* the driver initialisation suggests a layout of 4 main areas: 13 - * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). 12 + /* the driver initialisation suggests a layout of 4 areas 13 + * within the main card control I/O: 14 + * from 0x00 (playback codec), from 0x20 (recording codec) 15 + * and from 0x40 (most certainly I2S out codec). 14 16 * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, 15 17 * power management etc.???). */ 16 18 17 - /** playback area **/ 18 - #define IDX_IO_PLAY_FLAGS 0x00 /* PU:0x0000 */ 19 + #define AZF_IO_OFFS_CODEC_PLAYBACK 0x00 20 + #define AZF_IO_OFFS_CODEC_CAPTURE 0x20 21 + #define AZF_IO_OFFS_CODEC_I2S_OUT 0x40 22 + 23 + #define IDX_IO_CODEC_DMA_FLAGS 0x00 /* PU:0x0000 */ 19 24 /* able to reactivate output after output muting due to 8/16bit 20 25 * output change, just like 0x0002. 21 26 * 0x0001 is the only bit that's able to start the DMA counter */ 22 - #define DMA_RESUME 0x0001 /* paused if cleared ? */ 27 + #define DMA_RESUME 0x0001 /* paused if cleared? */ 23 28 /* 0x0002 *temporarily* set during DMA stopping. hmm 24 29 * both 0x0002 and 0x0004 set in playback setup. */ 25 30 /* able to reactivate output after output muting due to 8/16bit 26 31 * output change, just like 0x0001. */ 27 - #define DMA_PLAY_SOMETHING1 0x0002 /* \ alternated (toggled) */ 32 + #define DMA_RUN_SOMETHING1 0x0002 /* \ alternated (toggled) */ 28 33 /* 0x0004: NOT able to reactivate output */ 29 - #define DMA_PLAY_SOMETHING2 0x0004 /* / bits */ 34 + #define DMA_RUN_SOMETHING2 0x0004 /* / bits */ 30 35 #define SOMETHING_ALMOST_ALWAYS_SET 0x0008 /* ???; can be modified */ 31 36 #define DMA_EPILOGUE_SOMETHING 0x0010 32 37 #define DMA_SOMETHING_ELSE 0x0020 /* ??? */ 33 - #define SOMETHING_UNMODIFIABLE 0xffc0 /* unused ? not modifiable */ 34 - #define IDX_IO_PLAY_IRQTYPE 0x02 /* PU:0x0001 */ 38 + #define SOMETHING_UNMODIFIABLE 0xffc0 /* unused? not modifiable */ 39 + #define IDX_IO_CODEC_IRQTYPE 0x02 /* PU:0x0001 */ 35 40 /* write back to flags in case flags are set, in order to ACK IRQ in handler 36 41 * (bit 1 of port 0x64 indicates interrupt for one of these three types) 37 42 * sometimes in this case it just writes 0xffff to globally ACK all IRQs 38 43 * settings written are not reflected when reading back, though. 39 - * seems to be IRQ, too (frequently used: port |= 0x07 !), but who knows ? */ 40 - #define IRQ_PLAY_SOMETHING 0x0001 /* something & ACK */ 41 - #define IRQ_FINISHED_PLAYBUF_1 0x0002 /* 1st dmabuf finished & ACK */ 42 - #define IRQ_FINISHED_PLAYBUF_2 0x0004 /* 2nd dmabuf finished & ACK */ 44 + * seems to be IRQ, too (frequently used: port |= 0x07 !), but who knows? */ 45 + #define IRQ_SOMETHING 0x0001 /* something & ACK */ 46 + #define IRQ_FINISHED_DMABUF_1 0x0002 /* 1st dmabuf finished & ACK */ 47 + #define IRQ_FINISHED_DMABUF_2 0x0004 /* 2nd dmabuf finished & ACK */ 43 48 #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ 44 49 #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ 45 - #define IRQMASK_UNMODIFIABLE 0xffe0 /* unused ? not modifiable */ 46 - #define IDX_IO_PLAY_DMA_START_1 0x04 /* start address of 1st DMA play area, PU:0x00000000 */ 47 - #define IDX_IO_PLAY_DMA_START_2 0x08 /* start address of 2nd DMA play area, PU:0x00000000 */ 48 - #define IDX_IO_PLAY_DMA_LEN_1 0x0c /* length of 1st DMA play area, PU:0x0000 */ 49 - #define IDX_IO_PLAY_DMA_LEN_2 0x0e /* length of 2nd DMA play area, PU:0x0000 */ 50 - #define IDX_IO_PLAY_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */ 51 - #define IDX_IO_PLAY_DMA_CURROFS 0x14 /* offset within current DMA play area, PU:0x0000 */ 52 - #define IDX_IO_PLAY_SOUNDFORMAT 0x16 /* PU:0x0010 */ 50 + #define IRQMASK_UNMODIFIABLE 0xffe0 /* unused? not modifiable */ 51 + /* start address of 1st DMA transfer area, PU:0x00000000 */ 52 + #define IDX_IO_CODEC_DMA_START_1 0x04 53 + /* start address of 2nd DMA transfer area, PU:0x00000000 */ 54 + #define IDX_IO_CODEC_DMA_START_2 0x08 55 + /* both lengths of DMA transfer areas, PU:0x00000000 56 + length1: offset 0x0c, length2: offset 0x0e */ 57 + #define IDX_IO_CODEC_DMA_LENGTHS 0x0c 58 + #define IDX_IO_CODEC_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */ 59 + /* offset within current DMA transfer area, PU:0x0000 */ 60 + #define IDX_IO_CODEC_DMA_CURROFS 0x14 61 + #define IDX_IO_CODEC_SOUNDFORMAT 0x16 /* PU:0x0010 */ 53 62 /* all unspecified bits can't be modified */ 54 63 #define SOUNDFORMAT_FREQUENCY_MASK 0x000f 55 64 #define SOUNDFORMAT_XTAL1 0x00 ··· 85 76 #define SOUNDFORMAT_FLAG_16BIT 0x0010 86 77 #define SOUNDFORMAT_FLAG_2CHANNELS 0x0020 87 78 79 + 88 80 /* define frequency helpers, for maximum value safety */ 89 81 enum azf_freq_t { 90 82 #define AZF_FREQ(rate) AZF_FREQ_##rate = rate ··· 106 96 #undef AZF_FREQ 107 97 }; 108 98 109 - /** recording area (see also: playback bit flag definitions) **/ 110 - #define IDX_IO_REC_FLAGS 0x20 /* ??, PU:0x0000 */ 111 - #define IDX_IO_REC_IRQTYPE 0x22 /* ??, PU:0x0000 */ 112 - #define IRQ_REC_SOMETHING 0x0001 /* something & ACK */ 113 - #define IRQ_FINISHED_RECBUF_1 0x0002 /* 1st dmabuf finished & ACK */ 114 - #define IRQ_FINISHED_RECBUF_2 0x0004 /* 2nd dmabuf finished & ACK */ 115 - /* hmm, maybe these are just the corresponding *recording* flags ? 116 - * but OTOH they are most likely at port 0x22 instead */ 117 - #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ 118 - #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ 119 - #define IDX_IO_REC_DMA_START_1 0x24 /* PU:0x00000000 */ 120 - #define IDX_IO_REC_DMA_START_2 0x28 /* PU:0x00000000 */ 121 - #define IDX_IO_REC_DMA_LEN_1 0x2c /* PU:0x0000 */ 122 - #define IDX_IO_REC_DMA_LEN_2 0x2e /* PU:0x0000 */ 123 - #define IDX_IO_REC_DMA_CURRPOS 0x30 /* PU:0x00000000 */ 124 - #define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ 125 - #define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ 126 - 127 - /** hmm, what is this I/O area for? MPU401?? or external DAC via I2S?? (after playback, recording, ???, timer) **/ 128 - #define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ 129 - /* general */ 130 - #define IDX_IO_42H 0x42 /* PU:0x0001 */ 131 - 132 99 /** DirectX timer, main interrupt area (FIXME: and something else?) **/ 133 100 #define IDX_IO_TIMER_VALUE 0x60 /* found this timer area by pure luck :-) */ 134 101 /* timer countdown value; triggers IRQ when timer is finished */ ··· 125 138 126 139 #define IRQ_PLAYBACK 0x0001 127 140 #define IRQ_RECORDING 0x0002 128 - #define IRQ_UNKNOWN1 0x0004 /* most probably I2S port */ 141 + #define IRQ_I2S_OUT 0x0004 /* this IS I2S, right!? (untested) */ 129 142 #define IRQ_GAMEPORT 0x0008 /* Interrupt of Digital(ly) Enhanced Game Port */ 130 143 #define IRQ_MPU401 0x0010 131 144 #define IRQ_TIMER 0x0020 /* DirectX timer */ ··· 258 271 * 01 --> 1/20 259 272 * 11 --> 1/200: */ 260 273 #define GAME_HWCFG_ADC_COUNTER_FREQ_MASK 0x06 274 + 275 + /* FIXME: these values might be reversed... */ 276 + #define GAME_HWCFG_ADC_COUNTER_FREQ_STD 0 277 + #define GAME_HWCFG_ADC_COUNTER_FREQ_1_2 1 278 + #define GAME_HWCFG_ADC_COUNTER_FREQ_1_20 2 279 + #define GAME_HWCFG_ADC_COUNTER_FREQ_1_200 3 261 280 262 281 /* enable gameport legacy I/O address (0x200) 263 282 * I was unable to locate any configurability for a different address: */