| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | *      cmpci.c  --  C-Media PCI audio driver. | 
|  | 3 | * | 
|  | 4 | *      Copyright (C) 1999  C-media support (support@cmedia.com.tw) | 
|  | 5 | * | 
|  | 6 | *      Based on the PCI drivers by Thomas Sailer (sailer@ife.ee.ethz.ch) | 
|  | 7 | * | 
|  | 8 | * 	For update, visit: | 
|  | 9 | * 		http://www.cmedia.com.tw | 
|  | 10 | * | 
|  | 11 | *      This program is free software; you can redistribute it and/or modify | 
|  | 12 | *      it under the terms of the GNU General Public License as published by | 
|  | 13 | *      the Free Software Foundation; either version 2 of the License, or | 
|  | 14 | *      (at your option) any later version. | 
|  | 15 | * | 
|  | 16 | *      This program is distributed in the hope that it will be useful, | 
|  | 17 | *      but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 18 | *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 19 | *      GNU General Public License for more details. | 
|  | 20 | * | 
|  | 21 | *      You should have received a copy of the GNU General Public License | 
|  | 22 | *      along with this program; if not, write to the Free Software | 
|  | 23 | *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 24 | * | 
|  | 25 | * Special thanks to David C. Niemi, Jan Pfeifer | 
|  | 26 | * | 
|  | 27 | * | 
|  | 28 | * Module command line parameters: | 
|  | 29 | *   none so far | 
|  | 30 | * | 
|  | 31 | * | 
|  | 32 | *  Supported devices: | 
|  | 33 | *  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible | 
|  | 34 | *  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible | 
|  | 35 | *  /dev/midi   simple MIDI UART interface, no ioctl | 
|  | 36 | * | 
|  | 37 | *  The card has both an FM and a Wavetable synth, but I have to figure | 
|  | 38 | *  out first how to drive them... | 
|  | 39 | * | 
|  | 40 | *  Revision history | 
|  | 41 | *    06.05.98   0.1   Initial release | 
|  | 42 | *    10.05.98   0.2   Fixed many bugs, esp. ADC rate calculation | 
|  | 43 | *                     First stab at a simple midi interface (no bells&whistles) | 
|  | 44 | *    13.05.98   0.3   Fix stupid cut&paste error: set_adc_rate was called instead of | 
|  | 45 | *                     set_dac_rate in the FMODE_WRITE case in cm_open | 
|  | 46 | *                     Fix hwptr out of bounds (now mpg123 works) | 
|  | 47 | *    14.05.98   0.4   Don't allow excessive interrupt rates | 
|  | 48 | *    08.06.98   0.5   First release using Alan Cox' soundcore instead of miscdevice | 
|  | 49 | *    03.08.98   0.6   Do not include modversions.h | 
|  | 50 | *                     Now mixer behaviour can basically be selected between | 
|  | 51 | *                     "OSS documented" and "OSS actual" behaviour | 
|  | 52 | *    31.08.98   0.7   Fix realplayer problems - dac.count issues | 
|  | 53 | *    10.12.98   0.8   Fix drain_dac trying to wait on not yet initialized DMA | 
|  | 54 | *    16.12.98   0.9   Fix a few f_file & FMODE_ bugs | 
|  | 55 | *    06.01.99   0.10  remove the silly SA_INTERRUPT flag. | 
|  | 56 | *                     hopefully killed the egcs section type conflict | 
|  | 57 | *    12.03.99   0.11  cinfo.blocks should be reset after GETxPTR ioctl. | 
|  | 58 | *                     reported by Johan Maes <joma@telindus.be> | 
|  | 59 | *    22.03.99   0.12  return EAGAIN instead of EBUSY when O_NONBLOCK | 
|  | 60 | *                     read/write cannot be executed | 
|  | 61 | *    18.08.99   1.5   Only deallocate DMA buffer when unloading. | 
|  | 62 | *    02.09.99   1.6   Enable SPDIF LOOP | 
|  | 63 | *                     Change the mixer read back | 
|  | 64 | *    21.09.99   2.33  Use RCS version as driver version. | 
|  | 65 | *                     Add support for modem, S/PDIF loop and 4 channels. | 
|  | 66 | *                     (8738 only) | 
|  | 67 | *                     Fix bug cause x11amp cannot play. | 
|  | 68 | * | 
|  | 69 | *    Fixes: | 
|  | 70 | *    Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 
|  | 71 | *    18/05/2001 - .bss nitpicks, fix a bug in set_dac_channels where it | 
|  | 72 | *    		   was calling prog_dmabuf with s->lock held, call missing | 
|  | 73 | *    		   unlock_kernel in cm_midi_release | 
|  | 74 | *    08/10/2001 - use set_current_state in some more places | 
|  | 75 | * | 
|  | 76 | *	Carlos Eduardo Gorges <carlos@techlinux.com.br> | 
|  | 77 | *	Fri May 25 2001 | 
|  | 78 | *	- SMP support ( spin[un]lock* revision ) | 
|  | 79 | *	- speaker mixer support | 
|  | 80 | *	Mon Aug 13 2001 | 
|  | 81 | *	- optimizations and cleanups | 
|  | 82 | * | 
|  | 83 | *    03/01/2003 - open_mode fixes from Georg Acher <acher@in.tum.de> | 
|  | 84 | *	Simon Braunschmidt <brasimon@web.de> | 
|  | 85 | *     Sat Jan 31 2004 | 
|  | 86 | *	- provide support for opl3 FM by releasing IO range after initialization | 
|  | 87 | * | 
|  | 88 | *    ChenLi Tien <cltien@cmedia.com.tw> | 
|  | 89 | *    Mar 9 2004 | 
|  | 90 | *	- Fix S/PDIF out if spdif_loop enabled | 
|  | 91 | *	- Load opl3 driver if enabled (fmio in proper range) | 
|  | 92 | *	- Load mpu401 if enabled (mpuio in proper range) | 
|  | 93 | *    Apr 5 2004 | 
|  | 94 | *	- Fix DUAL_DAC dma synchronization bug | 
|  | 95 | *	- Check exist FM/MPU401 I/O before activate. | 
|  | 96 | *	- Add AFTM_S16_BE format support, so MPlayer/Xine can play AC3/mutlichannel | 
|  | 97 | *	  on Mac | 
|  | 98 | *	- Change to support kernel 2.6 so only small patch needed | 
|  | 99 | *	- All parameters default to 0 | 
|  | 100 | *	- Add spdif_out to send PCM through S/PDIF out jack | 
|  | 101 | *	- Add hw_copy to get 4-spaker output for general PCM/analog output | 
|  | 102 | * | 
|  | 103 | *    Stefan Thater <stefan.thaeter@gmx.de> | 
|  | 104 | *    Apr 5 2004 | 
|  | 105 | *	- Fix mute single channel for CD/Line-in/AUX-in | 
|  | 106 | */ | 
|  | 107 | /*****************************************************************************/ | 
|  | 108 |  | 
|  | 109 | #include <linux/config.h> | 
|  | 110 | #include <linux/module.h> | 
|  | 111 | #include <linux/string.h> | 
|  | 112 | #include <linux/interrupt.h> | 
|  | 113 | #include <linux/ioport.h> | 
|  | 114 | #include <linux/sched.h> | 
|  | 115 | #include <linux/delay.h> | 
|  | 116 | #include <linux/sound.h> | 
|  | 117 | #include <linux/slab.h> | 
|  | 118 | #include <linux/soundcard.h> | 
|  | 119 | #include <linux/pci.h> | 
|  | 120 | #include <linux/init.h> | 
|  | 121 | #include <linux/poll.h> | 
|  | 122 | #include <linux/spinlock.h> | 
|  | 123 | #include <linux/smp_lock.h> | 
|  | 124 | #include <linux/bitops.h> | 
|  | 125 | #include <linux/wait.h> | 
|  | 126 |  | 
|  | 127 | #include <asm/io.h> | 
|  | 128 | #include <asm/page.h> | 
|  | 129 | #include <asm/uaccess.h> | 
|  | 130 |  | 
|  | 131 | #ifdef CONFIG_SOUND_CMPCI_MIDI | 
|  | 132 | #include "sound_config.h" | 
|  | 133 | #include "mpu401.h" | 
|  | 134 | #endif | 
|  | 135 | #ifdef CONFIG_SOUND_CMPCI_FM | 
|  | 136 | #include "opl3.h" | 
|  | 137 | #endif | 
|  | 138 | #ifdef CONFIG_SOUND_CMPCI_JOYSTICK | 
|  | 139 | #include <linux/gameport.h> | 
|  | 140 | #endif | 
|  | 141 |  | 
|  | 142 | /* --------------------------------------------------------------------- */ | 
|  | 143 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 
|  | 144 | #undef DMABYTEIO | 
|  | 145 | #define	DBG(x) {} | 
|  | 146 | /* --------------------------------------------------------------------- */ | 
|  | 147 |  | 
|  | 148 | #define CM_MAGIC  ((PCI_VENDOR_ID_CMEDIA<<16)|PCI_DEVICE_ID_CMEDIA_CM8338A) | 
|  | 149 |  | 
|  | 150 | /* CM8338 registers definition ****************/ | 
|  | 151 |  | 
|  | 152 | #define CODEC_CMI_FUNCTRL0		(0x00) | 
|  | 153 | #define CODEC_CMI_FUNCTRL1		(0x04) | 
|  | 154 | #define CODEC_CMI_CHFORMAT		(0x08) | 
|  | 155 | #define CODEC_CMI_INT_HLDCLR		(0x0C) | 
|  | 156 | #define CODEC_CMI_INT_STATUS		(0x10) | 
|  | 157 | #define CODEC_CMI_LEGACY_CTRL		(0x14) | 
|  | 158 | #define CODEC_CMI_MISC_CTRL		(0x18) | 
|  | 159 | #define CODEC_CMI_TDMA_POS		(0x1C) | 
|  | 160 | #define CODEC_CMI_MIXER			(0x20) | 
|  | 161 | #define CODEC_SB16_DATA			(0x22) | 
|  | 162 | #define CODEC_SB16_ADDR			(0x23) | 
|  | 163 | #define CODEC_CMI_MIXER1		(0x24) | 
|  | 164 | #define CODEC_CMI_MIXER2		(0x25) | 
|  | 165 | #define CODEC_CMI_AUX_VOL		(0x26) | 
|  | 166 | #define CODEC_CMI_MISC			(0x27) | 
|  | 167 | #define CODEC_CMI_AC97			(0x28) | 
|  | 168 |  | 
|  | 169 | #define CODEC_CMI_CH0_FRAME1		(0x80) | 
|  | 170 | #define CODEC_CMI_CH0_FRAME2		(0x84) | 
|  | 171 | #define CODEC_CMI_CH1_FRAME1		(0x88) | 
|  | 172 | #define CODEC_CMI_CH1_FRAME2		(0x8C) | 
|  | 173 |  | 
|  | 174 | #define CODEC_CMI_SPDIF_CTRL		(0x90) | 
|  | 175 | #define CODEC_CMI_MISC_CTRL2		(0x92) | 
|  | 176 |  | 
|  | 177 | #define CODEC_CMI_EXT_REG		(0xF0) | 
|  | 178 |  | 
|  | 179 | /*  Mixer registers for SB16 ******************/ | 
|  | 180 |  | 
|  | 181 | #define DSP_MIX_DATARESETIDX		((unsigned char)(0x00)) | 
|  | 182 |  | 
|  | 183 | #define DSP_MIX_MASTERVOLIDX_L		((unsigned char)(0x30)) | 
|  | 184 | #define DSP_MIX_MASTERVOLIDX_R		((unsigned char)(0x31)) | 
|  | 185 | #define DSP_MIX_VOICEVOLIDX_L		((unsigned char)(0x32)) | 
|  | 186 | #define DSP_MIX_VOICEVOLIDX_R		((unsigned char)(0x33)) | 
|  | 187 | #define DSP_MIX_FMVOLIDX_L		((unsigned char)(0x34)) | 
|  | 188 | #define DSP_MIX_FMVOLIDX_R		((unsigned char)(0x35)) | 
|  | 189 | #define DSP_MIX_CDVOLIDX_L		((unsigned char)(0x36)) | 
|  | 190 | #define DSP_MIX_CDVOLIDX_R		((unsigned char)(0x37)) | 
|  | 191 | #define DSP_MIX_LINEVOLIDX_L		((unsigned char)(0x38)) | 
|  | 192 | #define DSP_MIX_LINEVOLIDX_R		((unsigned char)(0x39)) | 
|  | 193 |  | 
|  | 194 | #define DSP_MIX_MICVOLIDX		((unsigned char)(0x3A)) | 
|  | 195 | #define DSP_MIX_SPKRVOLIDX		((unsigned char)(0x3B)) | 
|  | 196 |  | 
|  | 197 | #define DSP_MIX_OUTMIXIDX		((unsigned char)(0x3C)) | 
|  | 198 |  | 
|  | 199 | #define DSP_MIX_ADCMIXIDX_L		((unsigned char)(0x3D)) | 
|  | 200 | #define DSP_MIX_ADCMIXIDX_R		((unsigned char)(0x3E)) | 
|  | 201 |  | 
|  | 202 | #define DSP_MIX_INGAINIDX_L		((unsigned char)(0x3F)) | 
|  | 203 | #define DSP_MIX_INGAINIDX_R		((unsigned char)(0x40)) | 
|  | 204 | #define DSP_MIX_OUTGAINIDX_L		((unsigned char)(0x41)) | 
|  | 205 | #define DSP_MIX_OUTGAINIDX_R		((unsigned char)(0x42)) | 
|  | 206 |  | 
|  | 207 | #define DSP_MIX_AGCIDX			((unsigned char)(0x43)) | 
|  | 208 |  | 
|  | 209 | #define DSP_MIX_TREBLEIDX_L		((unsigned char)(0x44)) | 
|  | 210 | #define DSP_MIX_TREBLEIDX_R		((unsigned char)(0x45)) | 
|  | 211 | #define DSP_MIX_BASSIDX_L		((unsigned char)(0x46)) | 
|  | 212 | #define DSP_MIX_BASSIDX_R		((unsigned char)(0x47)) | 
|  | 213 | #define DSP_MIX_EXTENSION		((unsigned char)(0xf0)) | 
|  | 214 | // pseudo register for AUX | 
|  | 215 | #define	DSP_MIX_AUXVOL_L		((unsigned char)(0x50)) | 
|  | 216 | #define	DSP_MIX_AUXVOL_R		((unsigned char)(0x51)) | 
|  | 217 |  | 
|  | 218 | // I/O length | 
|  | 219 | #define CM_EXTENT_CODEC	  0x100 | 
|  | 220 | #define CM_EXTENT_MIDI	  0x2 | 
|  | 221 | #define CM_EXTENT_SYNTH	  0x4 | 
|  | 222 | #define CM_EXTENT_GAME	  0x8 | 
|  | 223 |  | 
|  | 224 | // Function Control Register 0 (00h) | 
|  | 225 | #define CHADC0    	0x01 | 
|  | 226 | #define CHADC1    	0x02 | 
|  | 227 | #define PAUSE0	  	0x04 | 
|  | 228 | #define PAUSE1	  	0x08 | 
|  | 229 |  | 
|  | 230 | // Function Control Register 0+2 (02h) | 
|  | 231 | #define CHEN0     	0x01 | 
|  | 232 | #define CHEN1     	0x02 | 
|  | 233 | #define RST_CH0	  	0x04 | 
|  | 234 | #define RST_CH1	  	0x08 | 
|  | 235 |  | 
|  | 236 | // Function Control Register 1 (04h) | 
|  | 237 | #define JYSTK_EN	0x02 | 
|  | 238 | #define UART_EN		0x04 | 
|  | 239 | #define	SPDO2DAC	0x40 | 
|  | 240 | #define	SPDFLOOP	0x80 | 
|  | 241 |  | 
|  | 242 | // Function Control Register 1+1 (05h) | 
|  | 243 | #define	SPDF_0		0x01 | 
|  | 244 | #define	SPDF_1		0x02 | 
|  | 245 | #define	ASFC		0x1c | 
|  | 246 | #define	DSFC		0xe0 | 
|  | 247 | #define	SPDIF2DAC	(SPDF_1 << 8 | SPDO2DAC) | 
|  | 248 |  | 
|  | 249 | // Channel Format Register (08h) | 
|  | 250 | #define CM_CFMT_STEREO	0x01 | 
|  | 251 | #define CM_CFMT_16BIT	0x02 | 
|  | 252 | #define CM_CFMT_MASK	0x03 | 
|  | 253 | #define	POLVALID	0x20 | 
|  | 254 | #define	INVSPDIFI	0x80 | 
|  | 255 |  | 
|  | 256 | // Channel Format Register+2 (0ah) | 
|  | 257 | #define SPD24SEL	0x20 | 
|  | 258 |  | 
|  | 259 | // Channel Format Register+3 (0bh) | 
|  | 260 | #define CHB3D		0x20 | 
|  | 261 | #define CHB3D5C		0x80 | 
|  | 262 |  | 
|  | 263 | // Interrupt Hold/Clear Register+2 (0eh) | 
|  | 264 | #define	CH0_INT_EN	0x01 | 
|  | 265 | #define	CH1_INT_EN	0x02 | 
|  | 266 |  | 
|  | 267 | // Interrupt Register (10h) | 
|  | 268 | #define CHINT0		0x01 | 
|  | 269 | #define CHINT1		0x02 | 
|  | 270 | #define	CH0BUSY		0x04 | 
|  | 271 | #define	CH1BUSY		0x08 | 
|  | 272 |  | 
|  | 273 | // Legacy Control/Status Register+1 (15h) | 
|  | 274 | #define	EXBASEN		0x10 | 
|  | 275 | #define	BASE2LIN	0x20 | 
|  | 276 | #define	CENTR2LIN	0x40 | 
|  | 277 | #define	CB2LIN		(BASE2LIN | CENTR2LIN) | 
|  | 278 | #define	CHB3D6C		0x80 | 
|  | 279 |  | 
|  | 280 | // Legacy Control/Status Register+2 (16h) | 
|  | 281 | #define	DAC2SPDO	0x20 | 
|  | 282 | #define	SPDCOPYRHT	0x40 | 
|  | 283 | #define	ENSPDOUT	0x80 | 
|  | 284 |  | 
|  | 285 | // Legacy Control/Status Register+3 (17h) | 
|  | 286 | #define	FMSEL		0x03 | 
|  | 287 | #define	VSBSEL		0x0c | 
|  | 288 | #define	VMPU		0x60 | 
|  | 289 | #define	NXCHG		0x80 | 
|  | 290 |  | 
|  | 291 | // Miscellaneous Control Register (18h) | 
|  | 292 | #define	REAR2LIN	0x20 | 
|  | 293 | #define	MUTECH1		0x40 | 
|  | 294 | #define	ENCENTER	0x80 | 
|  | 295 |  | 
|  | 296 | // Miscellaneous Control Register+1 (19h) | 
|  | 297 | #define	SELSPDIFI2	0x01 | 
|  | 298 | #define	SPDF_AC97	0x80 | 
|  | 299 |  | 
|  | 300 | // Miscellaneous Control Register+2 (1ah) | 
|  | 301 | #define	AC3_EN		0x04 | 
|  | 302 | #define	FM_EN		0x08 | 
|  | 303 | #define	SPD32SEL	0x20 | 
|  | 304 | #define	XCHGDAC		0x40 | 
|  | 305 | #define	ENDBDAC		0x80 | 
|  | 306 |  | 
|  | 307 | // Miscellaneous Control Register+3 (1bh) | 
|  | 308 | #define	SPDIFI48K	0x01 | 
|  | 309 | #define	SPDO5V		0x02 | 
|  | 310 | #define	N4SPK3D		0x04 | 
|  | 311 | #define	RESET		0x40 | 
|  | 312 | #define	PWD		0x80 | 
|  | 313 | #define	SPDIF48K	(SPDIFI48K << 24 | SPDF_AC97 << 8) | 
|  | 314 |  | 
|  | 315 | // Mixer1 (24h) | 
|  | 316 | #define	CDPLAY		0x01 | 
|  | 317 | #define	X3DEN		0x02 | 
|  | 318 | #define	REAR2FRONT	0x10 | 
|  | 319 | #define	SPK4		0x20 | 
|  | 320 | #define	WSMUTE		0x40 | 
|  | 321 | #define	FMMUTE		0x80 | 
|  | 322 |  | 
|  | 323 | // Miscellaneous Register (27h) | 
|  | 324 | #define	SPDVALID	0x02 | 
|  | 325 | #define	CENTR2MIC	0x04 | 
|  | 326 |  | 
|  | 327 | // Miscellaneous Register2 (92h) | 
|  | 328 | #define	SPD32KFMT	0x10 | 
|  | 329 |  | 
|  | 330 | #define CM_CFMT_DACSHIFT   2 | 
|  | 331 | #define CM_CFMT_ADCSHIFT   0 | 
|  | 332 | #define CM_FREQ_DACSHIFT   5 | 
|  | 333 | #define CM_FREQ_ADCSHIFT   2 | 
|  | 334 | #define	RSTDAC	RST_CH1 | 
|  | 335 | #define	RSTADC	RST_CH0 | 
|  | 336 | #define	ENDAC	CHEN1 | 
|  | 337 | #define	ENADC	CHEN0 | 
|  | 338 | #define	PAUSEDAC	PAUSE1 | 
|  | 339 | #define	PAUSEADC	PAUSE0 | 
|  | 340 | #define CODEC_CMI_ADC_FRAME1	CODEC_CMI_CH0_FRAME1 | 
|  | 341 | #define CODEC_CMI_ADC_FRAME2	CODEC_CMI_CH0_FRAME2 | 
|  | 342 | #define CODEC_CMI_DAC_FRAME1	CODEC_CMI_CH1_FRAME1 | 
|  | 343 | #define CODEC_CMI_DAC_FRAME2	CODEC_CMI_CH1_FRAME2 | 
|  | 344 | #define	DACINT	CHINT1 | 
|  | 345 | #define	ADCINT	CHINT0 | 
|  | 346 | #define	DACBUSY	CH1BUSY | 
|  | 347 | #define	ADCBUSY	CH0BUSY | 
|  | 348 | #define	ENDACINT	CH1_INT_EN | 
|  | 349 | #define	ENADCINT	CH0_INT_EN | 
|  | 350 |  | 
|  | 351 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; | 
|  | 352 | static const unsigned sample_shift[]	= { 0, 1, 1, 2 }; | 
|  | 353 |  | 
|  | 354 | #define SND_DEV_DSP16   5 | 
|  | 355 |  | 
|  | 356 | #define NR_DEVICE 3		/* maximum number of devices */ | 
|  | 357 |  | 
|  | 358 | #define	set_dac1_rate	set_adc_rate | 
|  | 359 | #define	set_dac1_rate_unlocked	set_adc_rate_unlocked | 
|  | 360 | #define	stop_dac1	stop_adc | 
|  | 361 | #define	stop_dac1_unlocked	stop_adc_unlocked | 
|  | 362 | #define	get_dmadac1	get_dmaadc | 
|  | 363 |  | 
|  | 364 | static unsigned int devindex = 0; | 
|  | 365 |  | 
|  | 366 | //*********************************************/ | 
|  | 367 |  | 
|  | 368 | struct cm_state { | 
|  | 369 | /* magic */ | 
|  | 370 | unsigned int magic; | 
|  | 371 |  | 
|  | 372 | /* list of cmedia devices */ | 
|  | 373 | struct list_head devs; | 
|  | 374 |  | 
|  | 375 | /* the corresponding pci_dev structure */ | 
|  | 376 | struct pci_dev *dev; | 
|  | 377 |  | 
|  | 378 | int dev_audio;			/* soundcore stuff */ | 
|  | 379 | int dev_mixer; | 
|  | 380 |  | 
|  | 381 | unsigned int iosb, iobase, iosynth, | 
|  | 382 | iomidi, iogame, irq;	/* hardware resources */ | 
|  | 383 | unsigned short deviceid;		/* pci_id */ | 
|  | 384 |  | 
|  | 385 | struct {				/* mixer stuff */ | 
|  | 386 | unsigned int modcnt; | 
|  | 387 | unsigned short vol[13]; | 
|  | 388 | } mix; | 
|  | 389 |  | 
|  | 390 | unsigned int rateadc, ratedac;		/* wave stuff */ | 
|  | 391 | unsigned char fmt, enable; | 
|  | 392 |  | 
|  | 393 | spinlock_t lock; | 
|  | 394 | struct semaphore open_sem; | 
|  | 395 | mode_t open_mode; | 
|  | 396 | wait_queue_head_t open_wait; | 
|  | 397 |  | 
|  | 398 | struct dmabuf { | 
|  | 399 | void *rawbuf; | 
|  | 400 | dma_addr_t dmaaddr; | 
|  | 401 | unsigned buforder; | 
|  | 402 | unsigned numfrag; | 
|  | 403 | unsigned fragshift; | 
|  | 404 | unsigned hwptr, swptr; | 
|  | 405 | unsigned total_bytes; | 
|  | 406 | int count; | 
|  | 407 | unsigned error;		/* over/underrun */ | 
|  | 408 | wait_queue_head_t wait; | 
|  | 409 |  | 
|  | 410 | unsigned fragsize;	/* redundant, but makes calculations easier */ | 
|  | 411 | unsigned dmasize; | 
|  | 412 | unsigned fragsamples; | 
|  | 413 | unsigned dmasamples; | 
|  | 414 |  | 
|  | 415 | unsigned mapped:1;	/* OSS stuff */ | 
|  | 416 | unsigned ready:1; | 
|  | 417 | unsigned endcleared:1; | 
|  | 418 | unsigned enabled:1; | 
|  | 419 | unsigned ossfragshift; | 
|  | 420 | int ossmaxfrags; | 
|  | 421 | unsigned subdivision; | 
|  | 422 | } dma_dac, dma_adc; | 
|  | 423 |  | 
|  | 424 | #ifdef CONFIG_SOUND_CMPCI_MIDI | 
|  | 425 | int midi_devc; | 
|  | 426 | struct address_info mpu_data; | 
|  | 427 | #endif | 
|  | 428 | #ifdef CONFIG_SOUND_CMPCI_JOYSTICK | 
|  | 429 | struct gameport *gameport; | 
|  | 430 | #endif | 
|  | 431 |  | 
|  | 432 | int	chip_version; | 
|  | 433 | int	max_channels; | 
|  | 434 | int	curr_channels; | 
|  | 435 | int	capability;		/* HW capability, various for chip versions */ | 
|  | 436 |  | 
|  | 437 | int	status;			/* HW or SW state */ | 
|  | 438 |  | 
|  | 439 | int	spdif_counter;		/* spdif frame counter */ | 
|  | 440 | }; | 
|  | 441 |  | 
|  | 442 | /* flags used for capability */ | 
|  | 443 | #define	CAN_AC3_HW		0x00000001		/* 037 or later */ | 
|  | 444 | #define	CAN_AC3_SW		0x00000002		/* 033 or later */ | 
|  | 445 | #define	CAN_AC3			(CAN_AC3_HW | CAN_AC3_SW) | 
|  | 446 | #define CAN_DUAL_DAC		0x00000004		/* 033 or later */ | 
|  | 447 | #define	CAN_MULTI_CH_HW		0x00000008		/* 039 or later */ | 
|  | 448 | #define	CAN_MULTI_CH		(CAN_MULTI_CH_HW | CAN_DUAL_DAC) | 
|  | 449 | #define	CAN_LINE_AS_REAR	0x00000010		/* 033 or later */ | 
|  | 450 | #define	CAN_LINE_AS_BASS	0x00000020		/* 039 or later */ | 
|  | 451 | #define	CAN_MIC_AS_BASS		0x00000040		/* 039 or later */ | 
|  | 452 |  | 
|  | 453 | /* flags used for status */ | 
|  | 454 | #define	DO_AC3_HW		0x00000001 | 
|  | 455 | #define	DO_AC3_SW		0x00000002 | 
|  | 456 | #define	DO_AC3			(DO_AC3_HW | DO_AC3_SW) | 
|  | 457 | #define	DO_DUAL_DAC		0x00000004 | 
|  | 458 | #define	DO_MULTI_CH_HW		0x00000008 | 
|  | 459 | #define	DO_MULTI_CH		(DO_MULTI_CH_HW | DO_DUAL_DAC) | 
|  | 460 | #define	DO_LINE_AS_REAR		0x00000010		/* 033 or later */ | 
|  | 461 | #define	DO_LINE_AS_BASS		0x00000020		/* 039 or later */ | 
|  | 462 | #define	DO_MIC_AS_BASS		0x00000040		/* 039 or later */ | 
|  | 463 | #define	DO_SPDIF_OUT		0x00000100 | 
|  | 464 | #define	DO_SPDIF_IN		0x00000200 | 
|  | 465 | #define	DO_SPDIF_LOOP		0x00000400 | 
|  | 466 | #define	DO_BIGENDIAN_W		0x00001000		/* used in PowerPC */ | 
|  | 467 | #define	DO_BIGENDIAN_R		0x00002000		/* used in PowerPC */ | 
|  | 468 |  | 
|  | 469 | static LIST_HEAD(devs); | 
|  | 470 |  | 
|  | 471 | static	int	mpuio; | 
|  | 472 | static	int	fmio; | 
|  | 473 | static	int	joystick; | 
|  | 474 | static	int	spdif_inverse; | 
|  | 475 | static	int	spdif_loop; | 
|  | 476 | static	int	spdif_out; | 
|  | 477 | static	int	use_line_as_rear; | 
|  | 478 | static	int	use_line_as_bass; | 
|  | 479 | static	int	use_mic_as_bass; | 
|  | 480 | static	int	mic_boost; | 
|  | 481 | static	int	hw_copy; | 
|  | 482 | module_param(mpuio, int, 0); | 
|  | 483 | module_param(fmio, int, 0); | 
|  | 484 | module_param(joystick, bool, 0); | 
|  | 485 | module_param(spdif_inverse, bool, 0); | 
|  | 486 | module_param(spdif_loop, bool, 0); | 
|  | 487 | module_param(spdif_out, bool, 0); | 
|  | 488 | module_param(use_line_as_rear, bool, 0); | 
|  | 489 | module_param(use_line_as_bass, bool, 0); | 
|  | 490 | module_param(use_mic_as_bass, bool, 0); | 
|  | 491 | module_param(mic_boost, bool, 0); | 
|  | 492 | module_param(hw_copy, bool, 0); | 
|  | 493 | MODULE_PARM_DESC(mpuio, "(0x330, 0x320, 0x310, 0x300) Base of MPU-401, 0 to disable"); | 
|  | 494 | MODULE_PARM_DESC(fmio, "(0x388, 0x3C8, 0x3E0) Base of OPL3, 0 to disable"); | 
|  | 495 | MODULE_PARM_DESC(joystick, "(1/0) Enable joystick interface, still need joystick driver"); | 
|  | 496 | MODULE_PARM_DESC(spdif_inverse, "(1/0) Invert S/PDIF-in signal"); | 
|  | 497 | MODULE_PARM_DESC(spdif_loop, "(1/0) Route S/PDIF-in to S/PDIF-out directly"); | 
|  | 498 | MODULE_PARM_DESC(spdif_out, "(1/0) Send PCM to S/PDIF-out (PCM volume will not function)"); | 
|  | 499 | MODULE_PARM_DESC(use_line_as_rear, "(1/0) Use line-in jack as rear-out"); | 
|  | 500 | MODULE_PARM_DESC(use_line_as_bass, "(1/0) Use line-in jack as bass/center"); | 
|  | 501 | MODULE_PARM_DESC(use_mic_as_bass, "(1/0) Use mic-in jack as bass/center"); | 
|  | 502 | MODULE_PARM_DESC(mic_boost, "(1/0) Enable microphone boost"); | 
|  | 503 | MODULE_PARM_DESC(hw_copy, "Copy front channel to surround channel"); | 
|  | 504 |  | 
|  | 505 | /* --------------------------------------------------------------------- */ | 
|  | 506 |  | 
|  | 507 | static inline unsigned ld2(unsigned int x) | 
|  | 508 | { | 
|  | 509 | unsigned exp=16,l=5,r=0; | 
|  | 510 | static const unsigned num[]={0x2,0x4,0x10,0x100,0x10000}; | 
|  | 511 |  | 
|  | 512 | /* num: 2, 4, 16, 256, 65536 */ | 
|  | 513 | /* exp: 1, 2,  4,   8,    16 */ | 
|  | 514 |  | 
|  | 515 | while(l--) { | 
|  | 516 | if( x >= num[l] ) { | 
|  | 517 | if(num[l]>2) x >>= exp; | 
|  | 518 | r+=exp; | 
|  | 519 | } | 
|  | 520 | exp>>=1; | 
|  | 521 | } | 
|  | 522 |  | 
|  | 523 | return r; | 
|  | 524 | } | 
|  | 525 |  | 
|  | 526 | /* --------------------------------------------------------------------- */ | 
|  | 527 |  | 
|  | 528 | static void maskb(unsigned int addr, unsigned int mask, unsigned int value) | 
|  | 529 | { | 
|  | 530 | outb((inb(addr) & mask) | value, addr); | 
|  | 531 | } | 
|  | 532 |  | 
|  | 533 | static void maskw(unsigned int addr, unsigned int mask, unsigned int value) | 
|  | 534 | { | 
|  | 535 | outw((inw(addr) & mask) | value, addr); | 
|  | 536 | } | 
|  | 537 |  | 
|  | 538 | static void maskl(unsigned int addr, unsigned int mask, unsigned int value) | 
|  | 539 | { | 
|  | 540 | outl((inl(addr) & mask) | value, addr); | 
|  | 541 | } | 
|  | 542 |  | 
|  | 543 | static void set_dmadac1(struct cm_state *s, unsigned int addr, unsigned int count) | 
|  | 544 | { | 
|  | 545 | if (addr) | 
|  | 546 | outl(addr, s->iobase + CODEC_CMI_ADC_FRAME1); | 
|  | 547 | outw(count - 1, s->iobase + CODEC_CMI_ADC_FRAME2); | 
|  | 548 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~CHADC0, 0); | 
|  | 549 | } | 
|  | 550 |  | 
|  | 551 | static void set_dmaadc(struct cm_state *s, unsigned int addr, unsigned int count) | 
|  | 552 | { | 
|  | 553 | outl(addr, s->iobase + CODEC_CMI_ADC_FRAME1); | 
|  | 554 | outw(count - 1, s->iobase + CODEC_CMI_ADC_FRAME2); | 
|  | 555 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, CHADC0); | 
|  | 556 | } | 
|  | 557 |  | 
|  | 558 | static void set_dmadac(struct cm_state *s, unsigned int addr, unsigned int count) | 
|  | 559 | { | 
|  | 560 | outl(addr, s->iobase + CODEC_CMI_DAC_FRAME1); | 
|  | 561 | outw(count - 1, s->iobase + CODEC_CMI_DAC_FRAME2); | 
|  | 562 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~CHADC1, 0); | 
|  | 563 | if (s->status & DO_DUAL_DAC) | 
|  | 564 | set_dmadac1(s, 0, count); | 
|  | 565 | } | 
|  | 566 |  | 
|  | 567 | static void set_countadc(struct cm_state *s, unsigned count) | 
|  | 568 | { | 
|  | 569 | outw(count - 1, s->iobase + CODEC_CMI_ADC_FRAME2 + 2); | 
|  | 570 | } | 
|  | 571 |  | 
|  | 572 | static void set_countdac(struct cm_state *s, unsigned count) | 
|  | 573 | { | 
|  | 574 | outw(count - 1, s->iobase + CODEC_CMI_DAC_FRAME2 + 2); | 
|  | 575 | if (s->status & DO_DUAL_DAC) | 
|  | 576 | set_countadc(s, count); | 
|  | 577 | } | 
|  | 578 |  | 
|  | 579 | static unsigned get_dmadac(struct cm_state *s) | 
|  | 580 | { | 
|  | 581 | unsigned int curr_addr; | 
|  | 582 |  | 
|  | 583 | curr_addr = inw(s->iobase + CODEC_CMI_DAC_FRAME2) + 1; | 
|  | 584 | curr_addr <<= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]; | 
|  | 585 | curr_addr = s->dma_dac.dmasize - curr_addr; | 
|  | 586 |  | 
|  | 587 | return curr_addr; | 
|  | 588 | } | 
|  | 589 |  | 
|  | 590 | static unsigned get_dmaadc(struct cm_state *s) | 
|  | 591 | { | 
|  | 592 | unsigned int curr_addr; | 
|  | 593 |  | 
|  | 594 | curr_addr = inw(s->iobase + CODEC_CMI_ADC_FRAME2) + 1; | 
|  | 595 | curr_addr <<= sample_shift[(s->fmt >> CM_CFMT_ADCSHIFT) & CM_CFMT_MASK]; | 
|  | 596 | curr_addr = s->dma_adc.dmasize - curr_addr; | 
|  | 597 |  | 
|  | 598 | return curr_addr; | 
|  | 599 | } | 
|  | 600 |  | 
|  | 601 | static void wrmixer(struct cm_state *s, unsigned char idx, unsigned char data) | 
|  | 602 | { | 
|  | 603 | unsigned char regval, pseudo; | 
|  | 604 |  | 
|  | 605 | // pseudo register | 
|  | 606 | if (idx == DSP_MIX_AUXVOL_L) { | 
|  | 607 | data >>= 4; | 
|  | 608 | data &= 0x0f; | 
|  | 609 | regval = inb(s->iobase + CODEC_CMI_AUX_VOL) & ~0x0f; | 
|  | 610 | outb(regval | data, s->iobase + CODEC_CMI_AUX_VOL); | 
|  | 611 | return; | 
|  | 612 | } | 
|  | 613 | if (idx == DSP_MIX_AUXVOL_R) { | 
|  | 614 | data &= 0xf0; | 
|  | 615 | regval = inb(s->iobase + CODEC_CMI_AUX_VOL) & ~0xf0; | 
|  | 616 | outb(regval | data, s->iobase + CODEC_CMI_AUX_VOL); | 
|  | 617 | return; | 
|  | 618 | } | 
|  | 619 | outb(idx, s->iobase + CODEC_SB16_ADDR); | 
|  | 620 | udelay(10); | 
|  | 621 | // pseudo bits | 
|  | 622 | if (idx == DSP_MIX_OUTMIXIDX) { | 
|  | 623 | pseudo = data & ~0x1f; | 
|  | 624 | pseudo >>= 1; | 
|  | 625 | regval = inb(s->iobase + CODEC_CMI_MIXER2) & ~0x30; | 
|  | 626 | outb(regval | pseudo, s->iobase + CODEC_CMI_MIXER2); | 
|  | 627 | } | 
|  | 628 | if (idx == DSP_MIX_ADCMIXIDX_L) { | 
|  | 629 | pseudo = data & 0x80; | 
|  | 630 | pseudo >>= 1; | 
|  | 631 | regval = inb(s->iobase + CODEC_CMI_MIXER2) & ~0x40; | 
|  | 632 | outb(regval | pseudo, s->iobase + CODEC_CMI_MIXER2); | 
|  | 633 | } | 
|  | 634 | if (idx == DSP_MIX_ADCMIXIDX_R) { | 
|  | 635 | pseudo = data & 0x80; | 
|  | 636 | regval = inb(s->iobase + CODEC_CMI_MIXER2) & ~0x80; | 
|  | 637 | outb(regval | pseudo, s->iobase + CODEC_CMI_MIXER2); | 
|  | 638 | } | 
|  | 639 | outb(data, s->iobase + CODEC_SB16_DATA); | 
|  | 640 | udelay(10); | 
|  | 641 | } | 
|  | 642 |  | 
|  | 643 | static unsigned char rdmixer(struct cm_state *s, unsigned char idx) | 
|  | 644 | { | 
|  | 645 | unsigned char v, pseudo; | 
|  | 646 |  | 
|  | 647 | // pseudo register | 
|  | 648 | if (idx == DSP_MIX_AUXVOL_L) { | 
|  | 649 | v = inb(s->iobase + CODEC_CMI_AUX_VOL) & 0x0f; | 
|  | 650 | v <<= 4; | 
|  | 651 | return v; | 
|  | 652 | } | 
|  | 653 | if (idx == DSP_MIX_AUXVOL_L) { | 
|  | 654 | v = inb(s->iobase + CODEC_CMI_AUX_VOL) & 0xf0; | 
|  | 655 | return v; | 
|  | 656 | } | 
|  | 657 | outb(idx, s->iobase + CODEC_SB16_ADDR); | 
|  | 658 | udelay(10); | 
|  | 659 | v = inb(s->iobase + CODEC_SB16_DATA); | 
|  | 660 | udelay(10); | 
|  | 661 | // pseudo bits | 
|  | 662 | if (idx == DSP_MIX_OUTMIXIDX) { | 
|  | 663 | pseudo = inb(s->iobase + CODEC_CMI_MIXER2) & 0x30; | 
|  | 664 | pseudo <<= 1; | 
|  | 665 | v |= pseudo; | 
|  | 666 | } | 
|  | 667 | if (idx == DSP_MIX_ADCMIXIDX_L) { | 
|  | 668 | pseudo = inb(s->iobase + CODEC_CMI_MIXER2) & 0x40; | 
|  | 669 | pseudo <<= 1; | 
|  | 670 | v |= pseudo; | 
|  | 671 | } | 
|  | 672 | if (idx == DSP_MIX_ADCMIXIDX_R) { | 
|  | 673 | pseudo = inb(s->iobase + CODEC_CMI_MIXER2) & 0x80; | 
|  | 674 | v |= pseudo; | 
|  | 675 | } | 
|  | 676 | return v; | 
|  | 677 | } | 
|  | 678 |  | 
|  | 679 | static void set_fmt_unlocked(struct cm_state *s, unsigned char mask, unsigned char data) | 
|  | 680 | { | 
|  | 681 | if (mask && s->chip_version > 0) {	/* 8338 cannot keep this */ | 
|  | 682 | s->fmt = inb(s->iobase + CODEC_CMI_CHFORMAT); | 
|  | 683 | udelay(10); | 
|  | 684 | } | 
|  | 685 | s->fmt = (s->fmt & mask) | data; | 
|  | 686 | outb(s->fmt, s->iobase + CODEC_CMI_CHFORMAT); | 
|  | 687 | udelay(10); | 
|  | 688 | } | 
|  | 689 |  | 
|  | 690 | static void set_fmt(struct cm_state *s, unsigned char mask, unsigned char data) | 
|  | 691 | { | 
|  | 692 | unsigned long flags; | 
|  | 693 |  | 
|  | 694 | spin_lock_irqsave(&s->lock, flags); | 
|  | 695 | set_fmt_unlocked(s,mask,data); | 
|  | 696 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 697 | } | 
|  | 698 |  | 
|  | 699 | static void frobindir(struct cm_state *s, unsigned char idx, unsigned char mask, unsigned char data) | 
|  | 700 | { | 
|  | 701 | outb(idx, s->iobase + CODEC_SB16_ADDR); | 
|  | 702 | udelay(10); | 
|  | 703 | outb((inb(s->iobase + CODEC_SB16_DATA) & mask) | data, s->iobase + CODEC_SB16_DATA); | 
|  | 704 | udelay(10); | 
|  | 705 | } | 
|  | 706 |  | 
|  | 707 | static struct { | 
|  | 708 | unsigned	rate; | 
|  | 709 | unsigned	lower; | 
|  | 710 | unsigned	upper; | 
|  | 711 | unsigned char	freq; | 
|  | 712 | } rate_lookup[] = | 
|  | 713 | { | 
|  | 714 | { 5512,		(0 + 5512) / 2,		(5512 + 8000) / 2,	0 }, | 
|  | 715 | { 8000,		(5512 + 8000) / 2,	(8000 + 11025) / 2,	4 }, | 
|  | 716 | { 11025,	(8000 + 11025) / 2,	(11025 + 16000) / 2,	1 }, | 
|  | 717 | { 16000,	(11025 + 16000) / 2,	(16000 + 22050) / 2,	5 }, | 
|  | 718 | { 22050,	(16000 + 22050) / 2,	(22050 + 32000) / 2,	2 }, | 
|  | 719 | { 32000,	(22050 + 32000) / 2,	(32000 + 44100) / 2,	6 }, | 
|  | 720 | { 44100,	(32000 + 44100) / 2,	(44100 + 48000) / 2,	3 }, | 
|  | 721 | { 48000,	(44100 + 48000) / 2,	48000,			7 } | 
|  | 722 | }; | 
|  | 723 |  | 
|  | 724 | static void set_spdif_copyright(struct cm_state *s, int spdif_copyright) | 
|  | 725 | { | 
|  | 726 | /* enable SPDIF-in Copyright */ | 
|  | 727 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~SPDCOPYRHT, spdif_copyright ? SPDCOPYRHT : 0); | 
|  | 728 | } | 
|  | 729 |  | 
|  | 730 | static void set_spdif_loop(struct cm_state *s, int spdif_loop) | 
|  | 731 | { | 
|  | 732 | /* enable SPDIF loop */ | 
|  | 733 | if (spdif_loop) { | 
|  | 734 | s->status |= DO_SPDIF_LOOP; | 
|  | 735 | /* turn on spdif-in to spdif-out */ | 
|  | 736 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, SPDFLOOP); | 
|  | 737 | } else { | 
|  | 738 | s->status &= ~DO_SPDIF_LOOP; | 
|  | 739 | /* turn off spdif-in to spdif-out */ | 
|  | 740 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~SPDFLOOP, 0); | 
|  | 741 | } | 
|  | 742 | } | 
|  | 743 |  | 
|  | 744 | static void set_spdif_monitor(struct cm_state *s, int channel) | 
|  | 745 | { | 
|  | 746 | // SPDO2DAC | 
|  | 747 | maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~SPDO2DAC, channel == 2 ? SPDO2DAC : 0); | 
|  | 748 | // CDPLAY | 
|  | 749 | if (s->chip_version >= 39) | 
|  | 750 | maskb(s->iobase + CODEC_CMI_MIXER1, ~CDPLAY, channel ? CDPLAY : 0); | 
|  | 751 | } | 
|  | 752 |  | 
|  | 753 | static void set_spdifout_level(struct cm_state *s, int level5v) | 
|  | 754 | { | 
|  | 755 | /* SPDO5V */ | 
|  | 756 | if (s->chip_version > 0) | 
|  | 757 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~SPDO5V, level5v ? SPDO5V : 0); | 
|  | 758 | } | 
|  | 759 |  | 
|  | 760 | static void set_spdifin_inverse(struct cm_state *s, int spdif_inverse) | 
|  | 761 | { | 
|  | 762 | if (s->chip_version == 0)	/* 8338 has not this feature */ | 
|  | 763 | return; | 
|  | 764 | if (spdif_inverse) { | 
|  | 765 | /* turn on spdif-in inverse */ | 
|  | 766 | if (s->chip_version >= 39) | 
|  | 767 | maskb(s->iobase + CODEC_CMI_CHFORMAT, ~0, INVSPDIFI); | 
|  | 768 | else | 
|  | 769 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 1); | 
|  | 770 | } else { | 
|  | 771 | /* turn off spdif-ininverse */ | 
|  | 772 | if (s->chip_version >= 39) | 
|  | 773 | maskb(s->iobase + CODEC_CMI_CHFORMAT, ~INVSPDIFI, 0); | 
|  | 774 | else | 
|  | 775 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~1, 0); | 
|  | 776 | } | 
|  | 777 | } | 
|  | 778 |  | 
|  | 779 | static void set_spdifin_channel2(struct cm_state *s, int channel2) | 
|  | 780 | { | 
|  | 781 | /* SELSPDIFI2 */ | 
|  | 782 | if (s->chip_version >= 39) | 
|  | 783 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 1, ~SELSPDIFI2, channel2 ? SELSPDIFI2 : 0); | 
|  | 784 | } | 
|  | 785 |  | 
|  | 786 | static void set_spdifin_valid(struct cm_state *s, int valid) | 
|  | 787 | { | 
|  | 788 | /* SPDVALID */ | 
|  | 789 | maskb(s->iobase + CODEC_CMI_MISC, ~SPDVALID, valid ? SPDVALID : 0); | 
|  | 790 | } | 
|  | 791 |  | 
|  | 792 | static void set_spdifout_unlocked(struct cm_state *s, unsigned rate) | 
|  | 793 | { | 
|  | 794 | if (rate != 48000 && rate != 44100) | 
|  | 795 | rate = 0; | 
|  | 796 | if (rate == 48000 || rate == 44100) { | 
|  | 797 | set_spdif_loop(s, 0); | 
|  | 798 | // SPDF_1 | 
|  | 799 | maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0, SPDF_1); | 
|  | 800 | // SPDIFI48K SPDF_AC97 | 
|  | 801 | maskl(s->iobase + CODEC_CMI_MISC_CTRL, ~SPDIF48K, rate == 48000 ? SPDIF48K : 0); | 
|  | 802 | if (s->chip_version >= 55) | 
|  | 803 | // SPD32KFMT | 
|  | 804 | maskb(s->iobase + CODEC_CMI_MISC_CTRL2, ~SPD32KFMT, rate == 48000 ? SPD32KFMT : 0); | 
|  | 805 | if (s->chip_version > 0) | 
|  | 806 | // ENSPDOUT | 
|  | 807 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0, ENSPDOUT); | 
|  | 808 | // monitor SPDIF out | 
|  | 809 | set_spdif_monitor(s, 2); | 
|  | 810 | s->status |= DO_SPDIF_OUT; | 
|  | 811 | } else { | 
|  | 812 | maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~SPDF_1, 0); | 
|  | 813 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~ENSPDOUT, 0); | 
|  | 814 | // monitor none | 
|  | 815 | set_spdif_monitor(s, 0); | 
|  | 816 | s->status &= ~DO_SPDIF_OUT; | 
|  | 817 | } | 
|  | 818 | } | 
|  | 819 |  | 
|  | 820 | static void set_spdifout(struct cm_state *s, unsigned rate) | 
|  | 821 | { | 
|  | 822 | unsigned long flags; | 
|  | 823 |  | 
|  | 824 | spin_lock_irqsave(&s->lock, flags); | 
|  | 825 | set_spdifout_unlocked(s,rate); | 
|  | 826 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 827 | } | 
|  | 828 |  | 
|  | 829 | static void set_spdifin_unlocked(struct cm_state *s, unsigned rate) | 
|  | 830 | { | 
|  | 831 | if (rate == 48000 || rate == 44100) { | 
|  | 832 | // SPDF_1 | 
|  | 833 | maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0, SPDF_1); | 
|  | 834 | // SPDIFI48K SPDF_AC97 | 
|  | 835 | maskl(s->iobase + CODEC_CMI_MISC_CTRL, ~SPDIF48K, rate == 48000 ? SPDIF48K : 0); | 
|  | 836 | s->status |= DO_SPDIF_IN; | 
|  | 837 | } else { | 
|  | 838 | maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~SPDF_1, 0); | 
|  | 839 | s->status &= ~DO_SPDIF_IN; | 
|  | 840 | } | 
|  | 841 | } | 
|  | 842 |  | 
|  | 843 | static void set_spdifin(struct cm_state *s, unsigned rate) | 
|  | 844 | { | 
|  | 845 | unsigned long flags; | 
|  | 846 |  | 
|  | 847 | spin_lock_irqsave(&s->lock, flags); | 
|  | 848 | set_spdifin_unlocked(s,rate); | 
|  | 849 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 850 | } | 
|  | 851 |  | 
|  | 852 | /* find parity for bit 4~30 */ | 
|  | 853 | static unsigned parity(unsigned data) | 
|  | 854 | { | 
|  | 855 | unsigned parity = 0; | 
|  | 856 | int counter = 4; | 
|  | 857 |  | 
|  | 858 | data >>= 4;	// start from bit 4 | 
|  | 859 | while (counter <= 30) { | 
|  | 860 | if (data & 1) | 
|  | 861 | parity++; | 
|  | 862 | data >>= 1; | 
|  | 863 | counter++; | 
|  | 864 | } | 
|  | 865 | return parity & 1; | 
|  | 866 | } | 
|  | 867 |  | 
|  | 868 | static void set_ac3_unlocked(struct cm_state *s, unsigned rate) | 
|  | 869 | { | 
|  | 870 | if (!(s->capability & CAN_AC3)) | 
|  | 871 | return; | 
|  | 872 | /* enable AC3 */ | 
|  | 873 | if (rate && rate != 44100) | 
|  | 874 | rate = 48000; | 
|  | 875 | if (rate == 48000 || rate == 44100) { | 
|  | 876 | // mute DAC | 
|  | 877 | maskb(s->iobase + CODEC_CMI_MIXER1, ~0, WSMUTE); | 
|  | 878 | if (s->chip_version >= 39) | 
|  | 879 | maskb(s->iobase + CODEC_CMI_MISC_CTRL, ~0, MUTECH1); | 
|  | 880 | // AC3EN for 039, 0x04 | 
|  | 881 | if (s->chip_version >= 39) { | 
|  | 882 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, AC3_EN); | 
|  | 883 | if (s->chip_version == 55) | 
|  | 884 | maskb(s->iobase + CODEC_CMI_SPDIF_CTRL, ~2, 0); | 
|  | 885 | // AC3EN for 037, 0x10 | 
|  | 886 | } else if (s->chip_version == 37) | 
|  | 887 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x10); | 
|  | 888 | if (s->capability & CAN_AC3_HW) { | 
|  | 889 | // SPD24SEL for 039, 0x20, but cannot be set | 
|  | 890 | if (s->chip_version == 39) | 
|  | 891 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, SPD24SEL); | 
|  | 892 | // SPD24SEL for 037, 0x02 | 
|  | 893 | else if (s->chip_version == 37) | 
|  | 894 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x02); | 
|  | 895 | if (s->chip_version >= 39) | 
|  | 896 | maskb(s->iobase + CODEC_CMI_MIXER1, ~CDPLAY, 0); | 
|  | 897 |  | 
|  | 898 | s->status |= DO_AC3_HW; | 
|  | 899 | } else { | 
|  | 900 | // SPD32SEL for 037 & 039 | 
|  | 901 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, SPD32SEL); | 
|  | 902 | // set 176K sample rate to fix 033 HW bug | 
|  | 903 | if (s->chip_version == 33) { | 
|  | 904 | if (rate == 48000) | 
|  | 905 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0, 0x08); | 
|  | 906 | else | 
|  | 907 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0); | 
|  | 908 | } | 
|  | 909 | s->status |= DO_AC3_SW; | 
|  | 910 | } | 
|  | 911 | } else { | 
|  | 912 | maskb(s->iobase + CODEC_CMI_MIXER1, ~WSMUTE, 0); | 
|  | 913 | if (s->chip_version >= 39) | 
|  | 914 | maskb(s->iobase + CODEC_CMI_MISC_CTRL, ~MUTECH1, 0); | 
|  | 915 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~(SPD24SEL|0x12), 0); | 
|  | 916 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~(SPD32SEL|AC3_EN), 0); | 
|  | 917 | if (s->chip_version == 33) | 
|  | 918 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0); | 
|  | 919 | if (s->chip_version >= 39) | 
|  | 920 | maskb(s->iobase + CODEC_CMI_MIXER1, ~0, CDPLAY); | 
|  | 921 | s->status &= ~DO_AC3; | 
|  | 922 | } | 
|  | 923 | s->spdif_counter = 0; | 
|  | 924 | } | 
|  | 925 |  | 
|  | 926 | static void set_line_as_rear(struct cm_state *s, int use_line_as_rear) | 
|  | 927 | { | 
|  | 928 | if (!(s->capability & CAN_LINE_AS_REAR)) | 
|  | 929 | return; | 
|  | 930 | if (use_line_as_rear) { | 
|  | 931 | maskb(s->iobase + CODEC_CMI_MIXER1, ~0, SPK4); | 
|  | 932 | s->status |= DO_LINE_AS_REAR; | 
|  | 933 | } else { | 
|  | 934 | maskb(s->iobase + CODEC_CMI_MIXER1, ~SPK4, 0); | 
|  | 935 | s->status &= ~DO_LINE_AS_REAR; | 
|  | 936 | } | 
|  | 937 | } | 
|  | 938 |  | 
|  | 939 | static void set_line_as_bass(struct cm_state *s, int use_line_as_bass) | 
|  | 940 | { | 
|  | 941 | if (!(s->capability & CAN_LINE_AS_BASS)) | 
|  | 942 | return; | 
|  | 943 | if (use_line_as_bass) { | 
|  | 944 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0, CB2LIN); | 
|  | 945 | s->status |= DO_LINE_AS_BASS; | 
|  | 946 | } else { | 
|  | 947 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~CB2LIN, 0); | 
|  | 948 | s->status &= ~DO_LINE_AS_BASS; | 
|  | 949 | } | 
|  | 950 | } | 
|  | 951 |  | 
|  | 952 | static void set_mic_as_bass(struct cm_state *s, int use_mic_as_bass) | 
|  | 953 | { | 
|  | 954 | if (!(s->capability & CAN_MIC_AS_BASS)) | 
|  | 955 | return; | 
|  | 956 | if (use_mic_as_bass) { | 
|  | 957 | maskb(s->iobase + CODEC_CMI_MISC, ~0, 0x04); | 
|  | 958 | s->status |= DO_MIC_AS_BASS; | 
|  | 959 | } else { | 
|  | 960 | maskb(s->iobase + CODEC_CMI_MISC, ~0x04, 0); | 
|  | 961 | s->status &= ~DO_MIC_AS_BASS; | 
|  | 962 | } | 
|  | 963 | } | 
|  | 964 |  | 
|  | 965 | static void set_hw_copy(struct cm_state *s, int hw_copy) | 
|  | 966 | { | 
|  | 967 | if (s->max_channels > 2 && hw_copy) | 
|  | 968 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~0, N4SPK3D); | 
|  | 969 | else | 
|  | 970 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~N4SPK3D, 0); | 
|  | 971 | } | 
|  | 972 |  | 
|  | 973 | static void set_ac3(struct cm_state *s, unsigned rate) | 
|  | 974 | { | 
|  | 975 | unsigned long flags; | 
|  | 976 |  | 
|  | 977 | spin_lock_irqsave(&s->lock, flags); | 
|  | 978 | set_spdifout_unlocked(s, rate); | 
|  | 979 | set_ac3_unlocked(s, rate); | 
|  | 980 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 981 | } | 
|  | 982 |  | 
|  | 983 | static int trans_ac3(struct cm_state *s, void *dest, const char __user *source, int size) | 
|  | 984 | { | 
|  | 985 | int   i = size / 2; | 
|  | 986 | unsigned long data; | 
|  | 987 | unsigned short data16; | 
|  | 988 | unsigned long *dst = (unsigned long *) dest; | 
|  | 989 | unsigned short __user *src = (unsigned short __user *)source; | 
|  | 990 | int err; | 
|  | 991 |  | 
|  | 992 | do { | 
|  | 993 | if ((err = __get_user(data16, src++))) | 
|  | 994 | return err; | 
|  | 995 | data = (unsigned long)le16_to_cpu(data16); | 
|  | 996 | data <<= 12;			// ok for 16-bit data | 
|  | 997 | if (s->spdif_counter == 2 || s->spdif_counter == 3) | 
|  | 998 | data |= 0x40000000;	// indicate AC-3 raw data | 
|  | 999 | if (parity(data)) | 
|  | 1000 | data |= 0x80000000;	// parity | 
|  | 1001 | if (s->spdif_counter == 0) | 
|  | 1002 | data |= 3;		// preamble 'M' | 
|  | 1003 | else if (s->spdif_counter & 1) | 
|  | 1004 | data |= 5;		// odd, 'W' | 
|  | 1005 | else | 
|  | 1006 | data |= 9;		// even, 'M' | 
|  | 1007 | *dst++ = cpu_to_le32(data); | 
|  | 1008 | s->spdif_counter++; | 
|  | 1009 | if (s->spdif_counter == 384) | 
|  | 1010 | s->spdif_counter = 0; | 
|  | 1011 | } while (--i); | 
|  | 1012 |  | 
|  | 1013 | return 0; | 
|  | 1014 | } | 
|  | 1015 |  | 
|  | 1016 | static void set_adc_rate_unlocked(struct cm_state *s, unsigned rate) | 
|  | 1017 | { | 
|  | 1018 | unsigned char freq = 4; | 
|  | 1019 | int	i; | 
|  | 1020 |  | 
|  | 1021 | if (rate > 48000) | 
|  | 1022 | rate = 48000; | 
|  | 1023 | if (rate < 8000) | 
|  | 1024 | rate = 8000; | 
|  | 1025 | for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) { | 
|  | 1026 | if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) { | 
|  | 1027 | rate = rate_lookup[i].rate; | 
|  | 1028 | freq = rate_lookup[i].freq; | 
|  | 1029 | break; | 
|  | 1030 | } | 
|  | 1031 | } | 
|  | 1032 | s->rateadc = rate; | 
|  | 1033 | freq <<= CM_FREQ_ADCSHIFT; | 
|  | 1034 |  | 
|  | 1035 | maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~ASFC, freq); | 
|  | 1036 | } | 
|  | 1037 |  | 
|  | 1038 | static void set_adc_rate(struct cm_state *s, unsigned rate) | 
|  | 1039 | { | 
|  | 1040 | unsigned long flags; | 
|  | 1041 | unsigned char freq = 4; | 
|  | 1042 | int	i; | 
|  | 1043 |  | 
|  | 1044 | if (rate > 48000) | 
|  | 1045 | rate = 48000; | 
|  | 1046 | if (rate < 8000) | 
|  | 1047 | rate = 8000; | 
|  | 1048 | for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) { | 
|  | 1049 | if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) { | 
|  | 1050 | rate = rate_lookup[i].rate; | 
|  | 1051 | freq = rate_lookup[i].freq; | 
|  | 1052 | break; | 
|  | 1053 | } | 
|  | 1054 | } | 
|  | 1055 | s->rateadc = rate; | 
|  | 1056 | freq <<= CM_FREQ_ADCSHIFT; | 
|  | 1057 |  | 
|  | 1058 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1059 | maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~ASFC, freq); | 
|  | 1060 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1061 | } | 
|  | 1062 |  | 
|  | 1063 | static void set_dac_rate(struct cm_state *s, unsigned rate) | 
|  | 1064 | { | 
|  | 1065 | unsigned long flags; | 
|  | 1066 | unsigned char freq = 4; | 
|  | 1067 | int	i; | 
|  | 1068 |  | 
|  | 1069 | if (rate > 48000) | 
|  | 1070 | rate = 48000; | 
|  | 1071 | if (rate < 8000) | 
|  | 1072 | rate = 8000; | 
|  | 1073 | for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) { | 
|  | 1074 | if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) { | 
|  | 1075 | rate = rate_lookup[i].rate; | 
|  | 1076 | freq = rate_lookup[i].freq; | 
|  | 1077 | break; | 
|  | 1078 | } | 
|  | 1079 | } | 
|  | 1080 | s->ratedac = rate; | 
|  | 1081 | freq <<= CM_FREQ_DACSHIFT; | 
|  | 1082 |  | 
|  | 1083 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1084 | maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~DSFC, freq); | 
|  | 1085 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1086 |  | 
|  | 1087 | if (s->curr_channels <= 2 && spdif_out) | 
|  | 1088 | set_spdifout(s, rate); | 
|  | 1089 | if (s->status & DO_DUAL_DAC) | 
|  | 1090 | set_dac1_rate(s, rate); | 
|  | 1091 | } | 
|  | 1092 |  | 
|  | 1093 | /* --------------------------------------------------------------------- */ | 
|  | 1094 | static inline void reset_adc(struct cm_state *s) | 
|  | 1095 | { | 
|  | 1096 | /* reset bus master */ | 
|  | 1097 | outb(s->enable | RSTADC, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1098 | udelay(10); | 
|  | 1099 | outb(s->enable & ~RSTADC, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1100 | } | 
|  | 1101 |  | 
|  | 1102 | static inline void reset_dac(struct cm_state *s) | 
|  | 1103 | { | 
|  | 1104 | /* reset bus master */ | 
|  | 1105 | outb(s->enable | RSTDAC, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1106 | udelay(10); | 
|  | 1107 | outb(s->enable & ~RSTDAC, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1108 | if (s->status & DO_DUAL_DAC) | 
|  | 1109 | reset_adc(s); | 
|  | 1110 | } | 
|  | 1111 |  | 
|  | 1112 | static inline void pause_adc(struct cm_state *s) | 
|  | 1113 | { | 
|  | 1114 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, PAUSEADC); | 
|  | 1115 | } | 
|  | 1116 |  | 
|  | 1117 | static inline void pause_dac(struct cm_state *s) | 
|  | 1118 | { | 
|  | 1119 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, PAUSEDAC); | 
|  | 1120 | if (s->status & DO_DUAL_DAC) | 
|  | 1121 | pause_adc(s); | 
|  | 1122 | } | 
|  | 1123 |  | 
|  | 1124 | static inline void disable_adc(struct cm_state *s) | 
|  | 1125 | { | 
|  | 1126 | /* disable channel */ | 
|  | 1127 | s->enable &= ~ENADC; | 
|  | 1128 | outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1129 | reset_adc(s); | 
|  | 1130 | } | 
|  | 1131 |  | 
|  | 1132 | static inline void disable_dac(struct cm_state *s) | 
|  | 1133 | { | 
|  | 1134 | /* disable channel */ | 
|  | 1135 | s->enable &= ~ENDAC; | 
|  | 1136 | outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1137 | reset_dac(s); | 
|  | 1138 | if (s->status & DO_DUAL_DAC) | 
|  | 1139 | disable_adc(s); | 
|  | 1140 | } | 
|  | 1141 |  | 
|  | 1142 | static inline void enable_adc(struct cm_state *s) | 
|  | 1143 | { | 
|  | 1144 | if (!(s->enable & ENADC)) { | 
|  | 1145 | /* enable channel */ | 
|  | 1146 | s->enable |= ENADC; | 
|  | 1147 | outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1148 | } | 
|  | 1149 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~PAUSEADC, 0); | 
|  | 1150 | } | 
|  | 1151 |  | 
|  | 1152 | static inline void enable_dac_unlocked(struct cm_state *s) | 
|  | 1153 | { | 
|  | 1154 | if (!(s->enable & ENDAC)) { | 
|  | 1155 | /* enable channel */ | 
|  | 1156 | s->enable |= ENDAC; | 
|  | 1157 | outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2); | 
|  | 1158 | } | 
|  | 1159 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~PAUSEDAC, 0); | 
|  | 1160 |  | 
|  | 1161 | if (s->status & DO_DUAL_DAC) | 
|  | 1162 | enable_adc(s); | 
|  | 1163 | } | 
|  | 1164 |  | 
|  | 1165 | static inline void stop_adc_unlocked(struct cm_state *s) | 
|  | 1166 | { | 
|  | 1167 | if (s->enable & ENADC) { | 
|  | 1168 | /* disable interrupt */ | 
|  | 1169 | maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~ENADCINT, 0); | 
|  | 1170 | disable_adc(s); | 
|  | 1171 | } | 
|  | 1172 | } | 
|  | 1173 |  | 
|  | 1174 | static inline void stop_adc(struct cm_state *s) | 
|  | 1175 | { | 
|  | 1176 | unsigned long flags; | 
|  | 1177 |  | 
|  | 1178 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1179 | stop_adc_unlocked(s); | 
|  | 1180 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1181 |  | 
|  | 1182 | } | 
|  | 1183 |  | 
|  | 1184 | static inline void stop_dac_unlocked(struct cm_state *s) | 
|  | 1185 | { | 
|  | 1186 | if (s->enable & ENDAC) { | 
|  | 1187 | /* disable interrupt */ | 
|  | 1188 | maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~ENDACINT, 0); | 
|  | 1189 | disable_dac(s); | 
|  | 1190 | } | 
|  | 1191 | if (s->status & DO_DUAL_DAC) | 
|  | 1192 | stop_dac1_unlocked(s); | 
|  | 1193 | } | 
|  | 1194 |  | 
|  | 1195 | static inline void stop_dac(struct cm_state *s) | 
|  | 1196 | { | 
|  | 1197 | unsigned long flags; | 
|  | 1198 |  | 
|  | 1199 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1200 | stop_dac_unlocked(s); | 
|  | 1201 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1202 | } | 
|  | 1203 |  | 
|  | 1204 | static inline void start_adc_unlocked(struct cm_state *s) | 
|  | 1205 | { | 
|  | 1206 | if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) | 
|  | 1207 | && s->dma_adc.ready) { | 
|  | 1208 | /* enable interrupt */ | 
|  | 1209 | maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, ENADCINT); | 
|  | 1210 | enable_adc(s); | 
|  | 1211 | } | 
|  | 1212 | } | 
|  | 1213 |  | 
|  | 1214 | static void start_adc(struct cm_state *s) | 
|  | 1215 | { | 
|  | 1216 | unsigned long flags; | 
|  | 1217 |  | 
|  | 1218 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1219 | start_adc_unlocked(s); | 
|  | 1220 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1221 | } | 
|  | 1222 |  | 
|  | 1223 | static void start_dac1_unlocked(struct cm_state *s) | 
|  | 1224 | { | 
|  | 1225 | if ((s->dma_adc.mapped || s->dma_adc.count > 0) && s->dma_adc.ready) { | 
|  | 1226 | /* enable interrupt */ | 
|  | 1227 | maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, ENADCINT); | 
|  | 1228 | enable_dac_unlocked(s); | 
|  | 1229 | } | 
|  | 1230 | } | 
|  | 1231 |  | 
|  | 1232 | static void start_dac_unlocked(struct cm_state *s) | 
|  | 1233 | { | 
|  | 1234 | if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) { | 
|  | 1235 | /* enable interrupt */ | 
|  | 1236 | maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, ENDACINT); | 
|  | 1237 | enable_dac_unlocked(s); | 
|  | 1238 | } | 
|  | 1239 | if (s->status & DO_DUAL_DAC) | 
|  | 1240 | start_dac1_unlocked(s); | 
|  | 1241 | } | 
|  | 1242 |  | 
|  | 1243 | static void start_dac(struct cm_state *s) | 
|  | 1244 | { | 
|  | 1245 | unsigned long flags; | 
|  | 1246 |  | 
|  | 1247 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1248 | start_dac_unlocked(s); | 
|  | 1249 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1250 | } | 
|  | 1251 |  | 
|  | 1252 | static int prog_dmabuf(struct cm_state *s, unsigned rec); | 
|  | 1253 |  | 
|  | 1254 | static int set_dac_channels(struct cm_state *s, int channels) | 
|  | 1255 | { | 
|  | 1256 | unsigned long flags; | 
|  | 1257 | static unsigned int fmmute = 0; | 
|  | 1258 |  | 
|  | 1259 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1260 |  | 
|  | 1261 | if ((channels > 2) && (channels <= s->max_channels) | 
|  | 1262 | && (((s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK) == (CM_CFMT_STEREO | CM_CFMT_16BIT))) { | 
|  | 1263 | set_spdifout_unlocked(s, 0); | 
|  | 1264 | if (s->capability & CAN_MULTI_CH_HW) { | 
|  | 1265 | // NXCHG | 
|  | 1266 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0, NXCHG); | 
|  | 1267 | // CHB3D or CHB3D5C | 
|  | 1268 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 3, ~(CHB3D5C|CHB3D), channels > 4 ? CHB3D5C : CHB3D); | 
|  | 1269 | // CHB3D6C | 
|  | 1270 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~CHB3D6C, channels == 6 ? CHB3D6C : 0); | 
|  | 1271 | // ENCENTER | 
|  | 1272 | maskb(s->iobase + CODEC_CMI_MISC_CTRL, ~ENCENTER, channels == 6 ? ENCENTER : 0); | 
|  | 1273 | s->status |= DO_MULTI_CH_HW; | 
|  | 1274 | } else if (s->capability & CAN_DUAL_DAC) { | 
|  | 1275 | unsigned char fmtm = ~0, fmts = 0; | 
|  | 1276 | ssize_t ret; | 
|  | 1277 |  | 
|  | 1278 | // ENDBDAC, turn on double DAC mode | 
|  | 1279 | // XCHGDAC, CH0 -> back, CH1->front | 
|  | 1280 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, ENDBDAC|XCHGDAC); | 
|  | 1281 | // mute FM | 
|  | 1282 | fmmute = inb(s->iobase + CODEC_CMI_MIXER1) & FMMUTE; | 
|  | 1283 | maskb(s->iobase + CODEC_CMI_MIXER1, ~0, FMMUTE); | 
|  | 1284 | s->status |= DO_DUAL_DAC; | 
|  | 1285 | // prepare secondary buffer | 
|  | 1286 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1287 | ret = prog_dmabuf(s, 1); | 
|  | 1288 | if (ret) return ret; | 
|  | 1289 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1290 |  | 
|  | 1291 | // copy the hw state | 
|  | 1292 | fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT); | 
|  | 1293 | fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT); | 
|  | 1294 | // the HW only support 16-bit stereo | 
|  | 1295 | fmts |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; | 
|  | 1296 | fmts |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT; | 
|  | 1297 | fmts |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; | 
|  | 1298 | fmts |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; | 
|  | 1299 |  | 
|  | 1300 | set_fmt_unlocked(s, fmtm, fmts); | 
|  | 1301 | set_adc_rate_unlocked(s, s->ratedac); | 
|  | 1302 | } | 
|  | 1303 | // disable 4 speaker mode (analog duplicate) | 
|  | 1304 | set_hw_copy(s, 0); | 
|  | 1305 | s->curr_channels = channels; | 
|  | 1306 |  | 
|  | 1307 | // enable jack redirect | 
|  | 1308 | set_line_as_rear(s, use_line_as_rear); | 
|  | 1309 | if (channels > 4) { | 
|  | 1310 | set_line_as_bass(s, use_line_as_bass); | 
|  | 1311 | set_mic_as_bass(s, use_mic_as_bass); | 
|  | 1312 | } | 
|  | 1313 | } else { | 
|  | 1314 | if (s->status & DO_MULTI_CH_HW) { | 
|  | 1315 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~NXCHG, 0); | 
|  | 1316 | maskb(s->iobase + CODEC_CMI_CHFORMAT + 3, ~(CHB3D5C|CHB3D), 0); | 
|  | 1317 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~CHB3D6C, 0); | 
|  | 1318 | } else if (s->status & DO_DUAL_DAC) { | 
|  | 1319 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~ENDBDAC, 0); | 
|  | 1320 | maskb(s->iobase + CODEC_CMI_MIXER1, ~FMMUTE, fmmute); | 
|  | 1321 | } | 
|  | 1322 | // enable 4 speaker mode (analog duplicate) | 
|  | 1323 | set_hw_copy(s, hw_copy); | 
|  | 1324 | s->status &= ~DO_MULTI_CH; | 
|  | 1325 | s->curr_channels = s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1; | 
|  | 1326 | // disable jack redirect | 
|  | 1327 | set_line_as_rear(s, hw_copy ? use_line_as_rear : 0); | 
|  | 1328 | set_line_as_bass(s, 0); | 
|  | 1329 | set_mic_as_bass(s, 0); | 
|  | 1330 | } | 
|  | 1331 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1332 | return s->curr_channels; | 
|  | 1333 | } | 
|  | 1334 |  | 
|  | 1335 | /* --------------------------------------------------------------------- */ | 
|  | 1336 |  | 
|  | 1337 | #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) | 
|  | 1338 | #define DMABUF_MINORDER 1 | 
|  | 1339 |  | 
|  | 1340 | static void dealloc_dmabuf(struct cm_state *s, struct dmabuf *db) | 
|  | 1341 | { | 
|  | 1342 | struct page *pstart, *pend; | 
|  | 1343 |  | 
|  | 1344 | if (db->rawbuf) { | 
|  | 1345 | /* undo marking the pages as reserved */ | 
|  | 1346 | pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); | 
|  | 1347 | for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++) | 
|  | 1348 | ClearPageReserved(pstart); | 
|  | 1349 | pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr); | 
|  | 1350 | } | 
|  | 1351 | db->rawbuf = NULL; | 
|  | 1352 | db->mapped = db->ready = 0; | 
|  | 1353 | } | 
|  | 1354 |  | 
|  | 1355 | /* Ch1 is used for playback, Ch0 is used for recording */ | 
|  | 1356 |  | 
|  | 1357 | static int prog_dmabuf(struct cm_state *s, unsigned rec) | 
|  | 1358 | { | 
|  | 1359 | struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac; | 
|  | 1360 | unsigned rate = rec ? s->rateadc : s->ratedac; | 
|  | 1361 | int order; | 
|  | 1362 | unsigned bytepersec; | 
|  | 1363 | unsigned bufs; | 
|  | 1364 | struct page *pstart, *pend; | 
|  | 1365 | unsigned char fmt; | 
|  | 1366 | unsigned long flags; | 
|  | 1367 |  | 
|  | 1368 | fmt = s->fmt; | 
|  | 1369 | if (rec) { | 
|  | 1370 | stop_adc(s); | 
|  | 1371 | fmt >>= CM_CFMT_ADCSHIFT; | 
|  | 1372 | } else { | 
|  | 1373 | stop_dac(s); | 
|  | 1374 | fmt >>= CM_CFMT_DACSHIFT; | 
|  | 1375 | } | 
|  | 1376 |  | 
|  | 1377 | fmt &= CM_CFMT_MASK; | 
|  | 1378 | db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; | 
|  | 1379 | if (!db->rawbuf) { | 
|  | 1380 | db->ready = db->mapped = 0; | 
|  | 1381 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) | 
|  | 1382 | if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr))) | 
|  | 1383 | break; | 
|  | 1384 | if (!db->rawbuf || !db->dmaaddr) | 
|  | 1385 | return -ENOMEM; | 
|  | 1386 | db->buforder = order; | 
|  | 1387 | /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */ | 
|  | 1388 | pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); | 
|  | 1389 | for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++) | 
|  | 1390 | SetPageReserved(pstart); | 
|  | 1391 | } | 
|  | 1392 | bytepersec = rate << sample_shift[fmt]; | 
|  | 1393 | bufs = PAGE_SIZE << db->buforder; | 
|  | 1394 | if (db->ossfragshift) { | 
|  | 1395 | if ((1000 << db->ossfragshift) < bytepersec) | 
|  | 1396 | db->fragshift = ld2(bytepersec/1000); | 
|  | 1397 | else | 
|  | 1398 | db->fragshift = db->ossfragshift; | 
|  | 1399 | } else { | 
|  | 1400 | db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1)); | 
|  | 1401 | if (db->fragshift < 3) | 
|  | 1402 | db->fragshift = 3; | 
|  | 1403 | } | 
|  | 1404 | db->numfrag = bufs >> db->fragshift; | 
|  | 1405 | while (db->numfrag < 4 && db->fragshift > 3) { | 
|  | 1406 | db->fragshift--; | 
|  | 1407 | db->numfrag = bufs >> db->fragshift; | 
|  | 1408 | } | 
|  | 1409 | db->fragsize = 1 << db->fragshift; | 
|  | 1410 | if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) | 
|  | 1411 | db->numfrag = db->ossmaxfrags; | 
|  | 1412 | /* to make fragsize >= 4096 */ | 
|  | 1413 | db->fragsamples = db->fragsize >> sample_shift[fmt]; | 
|  | 1414 | db->dmasize = db->numfrag << db->fragshift; | 
|  | 1415 | db->dmasamples = db->dmasize >> sample_shift[fmt]; | 
|  | 1416 | memset(db->rawbuf, (fmt & CM_CFMT_16BIT) ? 0 : 0x80, db->dmasize); | 
|  | 1417 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1418 | if (rec) { | 
|  | 1419 | if (s->status & DO_DUAL_DAC) | 
|  | 1420 | set_dmadac1(s, db->dmaaddr, db->dmasize >> sample_shift[fmt]); | 
|  | 1421 | else | 
|  | 1422 | set_dmaadc(s, db->dmaaddr, db->dmasize >> sample_shift[fmt]); | 
|  | 1423 | /* program sample counts */ | 
|  | 1424 | set_countdac(s, db->fragsamples); | 
|  | 1425 | } else { | 
|  | 1426 | set_dmadac(s, db->dmaaddr, db->dmasize >> sample_shift[fmt]); | 
|  | 1427 | /* program sample counts */ | 
|  | 1428 | set_countdac(s, db->fragsamples); | 
|  | 1429 | } | 
|  | 1430 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1431 | db->enabled = 1; | 
|  | 1432 | db->ready = 1; | 
|  | 1433 | return 0; | 
|  | 1434 | } | 
|  | 1435 |  | 
|  | 1436 | static inline void clear_advance(struct cm_state *s) | 
|  | 1437 | { | 
|  | 1438 | unsigned char c = (s->fmt & (CM_CFMT_16BIT << CM_CFMT_DACSHIFT)) ? 0 : 0x80; | 
|  | 1439 | unsigned char *buf = s->dma_dac.rawbuf; | 
|  | 1440 | unsigned char *buf1 = s->dma_adc.rawbuf; | 
|  | 1441 | unsigned bsize = s->dma_dac.dmasize; | 
|  | 1442 | unsigned bptr = s->dma_dac.swptr; | 
|  | 1443 | unsigned len = s->dma_dac.fragsize; | 
|  | 1444 |  | 
|  | 1445 | if (bptr + len > bsize) { | 
|  | 1446 | unsigned x = bsize - bptr; | 
|  | 1447 | memset(buf + bptr, c, x); | 
|  | 1448 | if (s->status & DO_DUAL_DAC) | 
|  | 1449 | memset(buf1 + bptr, c, x); | 
|  | 1450 | bptr = 0; | 
|  | 1451 | len -= x; | 
|  | 1452 | } | 
|  | 1453 | memset(buf + bptr, c, len); | 
|  | 1454 | if (s->status & DO_DUAL_DAC) | 
|  | 1455 | memset(buf1 + bptr, c, len); | 
|  | 1456 | } | 
|  | 1457 |  | 
|  | 1458 | /* call with spinlock held! */ | 
|  | 1459 | static void cm_update_ptr(struct cm_state *s) | 
|  | 1460 | { | 
|  | 1461 | unsigned hwptr; | 
|  | 1462 | int diff; | 
|  | 1463 |  | 
|  | 1464 | /* update ADC pointer */ | 
|  | 1465 | if (s->dma_adc.ready) { | 
|  | 1466 | if (s->status & DO_DUAL_DAC) { | 
|  | 1467 | /* the dac part will finish for this */ | 
|  | 1468 | } else { | 
|  | 1469 | hwptr = get_dmaadc(s) % s->dma_adc.dmasize; | 
|  | 1470 | diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize; | 
|  | 1471 | s->dma_adc.hwptr = hwptr; | 
|  | 1472 | s->dma_adc.total_bytes += diff; | 
|  | 1473 | s->dma_adc.count += diff; | 
|  | 1474 | if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) | 
|  | 1475 | wake_up(&s->dma_adc.wait); | 
|  | 1476 | if (!s->dma_adc.mapped) { | 
|  | 1477 | if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { | 
|  | 1478 | pause_adc(s); | 
|  | 1479 | s->dma_adc.error++; | 
|  | 1480 | } | 
|  | 1481 | } | 
|  | 1482 | } | 
|  | 1483 | } | 
|  | 1484 | /* update DAC pointer */ | 
|  | 1485 | if (s->dma_dac.ready) { | 
|  | 1486 | hwptr = get_dmadac(s) % s->dma_dac.dmasize; | 
|  | 1487 | diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize; | 
|  | 1488 | s->dma_dac.hwptr = hwptr; | 
|  | 1489 | s->dma_dac.total_bytes += diff; | 
|  | 1490 | if (s->status & DO_DUAL_DAC) { | 
|  | 1491 | s->dma_adc.hwptr = hwptr; | 
|  | 1492 | s->dma_adc.total_bytes += diff; | 
|  | 1493 | } | 
|  | 1494 | if (s->dma_dac.mapped) { | 
|  | 1495 | s->dma_dac.count += diff; | 
|  | 1496 | if (s->status & DO_DUAL_DAC) | 
|  | 1497 | s->dma_adc.count += diff; | 
|  | 1498 | if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) | 
|  | 1499 | wake_up(&s->dma_dac.wait); | 
|  | 1500 | } else { | 
|  | 1501 | s->dma_dac.count -= diff; | 
|  | 1502 | if (s->status & DO_DUAL_DAC) | 
|  | 1503 | s->dma_adc.count -= diff; | 
|  | 1504 | if (s->dma_dac.count <= 0) { | 
|  | 1505 | pause_dac(s); | 
|  | 1506 | s->dma_dac.error++; | 
|  | 1507 | } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) { | 
|  | 1508 | clear_advance(s); | 
|  | 1509 | s->dma_dac.endcleared = 1; | 
|  | 1510 | if (s->status & DO_DUAL_DAC) | 
|  | 1511 | s->dma_adc.endcleared = 1; | 
|  | 1512 | } | 
|  | 1513 | if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize) | 
|  | 1514 | wake_up(&s->dma_dac.wait); | 
|  | 1515 | } | 
|  | 1516 | } | 
|  | 1517 | } | 
|  | 1518 |  | 
|  | 1519 | static irqreturn_t cm_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 
|  | 1520 | { | 
|  | 1521 | struct cm_state *s = (struct cm_state *)dev_id; | 
|  | 1522 | unsigned int intsrc, intstat; | 
|  | 1523 | unsigned char mask = 0; | 
|  | 1524 |  | 
|  | 1525 | /* fastpath out, to ease interrupt sharing */ | 
|  | 1526 | intsrc = inl(s->iobase + CODEC_CMI_INT_STATUS); | 
|  | 1527 | if (!(intsrc & 0x80000000)) | 
|  | 1528 | return IRQ_NONE; | 
|  | 1529 | spin_lock(&s->lock); | 
|  | 1530 | intstat = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2); | 
|  | 1531 | /* acknowledge interrupt */ | 
|  | 1532 | if (intsrc & ADCINT) | 
|  | 1533 | mask |= ENADCINT; | 
|  | 1534 | if (intsrc & DACINT) | 
|  | 1535 | mask |= ENDACINT; | 
|  | 1536 | outb(intstat & ~mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2); | 
|  | 1537 | outb(intstat | mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2); | 
|  | 1538 | cm_update_ptr(s); | 
|  | 1539 | spin_unlock(&s->lock); | 
|  | 1540 | #ifdef CONFIG_SOUND_CMPCI_MIDI | 
|  | 1541 | if (intsrc & 0x00010000) {	// UART interrupt | 
|  | 1542 | if (s->midi_devc && intchk_mpu401((void *)s->midi_devc)) | 
|  | 1543 | mpuintr(irq, (void *)s->midi_devc, regs); | 
|  | 1544 | else | 
|  | 1545 | inb(s->iomidi);// dummy read | 
|  | 1546 | } | 
|  | 1547 | #endif | 
|  | 1548 | return IRQ_HANDLED; | 
|  | 1549 | } | 
|  | 1550 |  | 
|  | 1551 | /* --------------------------------------------------------------------- */ | 
|  | 1552 |  | 
|  | 1553 | static const char invalid_magic[] = KERN_CRIT "cmpci: invalid magic value\n"; | 
|  | 1554 |  | 
|  | 1555 | #define VALIDATE_STATE(s)                         \ | 
|  | 1556 | ({                                                \ | 
|  | 1557 | if (!(s) || (s)->magic != CM_MAGIC) { \ | 
|  | 1558 | printk(invalid_magic);            \ | 
|  | 1559 | return -ENXIO;                    \ | 
|  | 1560 | }                                         \ | 
|  | 1561 | }) | 
|  | 1562 |  | 
|  | 1563 | /* --------------------------------------------------------------------- */ | 
|  | 1564 |  | 
|  | 1565 | #define MT_4          1 | 
|  | 1566 | #define MT_5MUTE      2 | 
|  | 1567 | #define MT_4MUTEMONO  3 | 
|  | 1568 | #define MT_6MUTE      4 | 
|  | 1569 | #define MT_5MUTEMONO  5 | 
|  | 1570 |  | 
|  | 1571 | static const struct { | 
|  | 1572 | unsigned left; | 
|  | 1573 | unsigned right; | 
|  | 1574 | unsigned type; | 
|  | 1575 | unsigned rec; | 
|  | 1576 | unsigned play; | 
|  | 1577 | } mixtable[SOUND_MIXER_NRDEVICES] = { | 
|  | 1578 | [SOUND_MIXER_CD]     = { DSP_MIX_CDVOLIDX_L,     DSP_MIX_CDVOLIDX_R,     MT_5MUTE,     0x04, 0x06 }, | 
|  | 1579 | [SOUND_MIXER_LINE]   = { DSP_MIX_LINEVOLIDX_L,   DSP_MIX_LINEVOLIDX_R,   MT_5MUTE,     0x10, 0x18 }, | 
|  | 1580 | [SOUND_MIXER_MIC]    = { DSP_MIX_MICVOLIDX,      DSP_MIX_MICVOLIDX,      MT_5MUTEMONO, 0x01, 0x01 }, | 
|  | 1581 | [SOUND_MIXER_SYNTH]  = { DSP_MIX_FMVOLIDX_L,  	 DSP_MIX_FMVOLIDX_R,     MT_5MUTE,     0x40, 0x00 }, | 
|  | 1582 | [SOUND_MIXER_VOLUME] = { DSP_MIX_MASTERVOLIDX_L, DSP_MIX_MASTERVOLIDX_R, MT_5MUTE,     0x00, 0x00 }, | 
|  | 1583 | [SOUND_MIXER_PCM]    = { DSP_MIX_VOICEVOLIDX_L,  DSP_MIX_VOICEVOLIDX_R,  MT_5MUTE,     0x00, 0x00 }, | 
|  | 1584 | [SOUND_MIXER_LINE1]  = { DSP_MIX_AUXVOL_L,       DSP_MIX_AUXVOL_R,       MT_5MUTE,     0x80, 0x60 }, | 
|  | 1585 | [SOUND_MIXER_SPEAKER]= { DSP_MIX_SPKRVOLIDX,	 DSP_MIX_SPKRVOLIDX,	 MT_5MUTEMONO, 0x00, 0x01 } | 
|  | 1586 | }; | 
|  | 1587 |  | 
|  | 1588 | static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = | 
|  | 1589 | { | 
|  | 1590 | [SOUND_MIXER_CD]     = 1, | 
|  | 1591 | [SOUND_MIXER_LINE]   = 2, | 
|  | 1592 | [SOUND_MIXER_MIC]    = 3, | 
|  | 1593 | [SOUND_MIXER_SYNTH]  = 4, | 
|  | 1594 | [SOUND_MIXER_VOLUME] = 5, | 
|  | 1595 | [SOUND_MIXER_PCM]    = 6, | 
|  | 1596 | [SOUND_MIXER_LINE1]  = 7, | 
|  | 1597 | [SOUND_MIXER_SPEAKER]= 8 | 
|  | 1598 | }; | 
|  | 1599 |  | 
|  | 1600 | static unsigned mixer_outmask(struct cm_state *s) | 
|  | 1601 | { | 
|  | 1602 | unsigned long flags; | 
|  | 1603 | int i, j, k; | 
|  | 1604 |  | 
|  | 1605 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1606 | j = rdmixer(s, DSP_MIX_OUTMIXIDX); | 
|  | 1607 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1608 | for (k = i = 0; i < SOUND_MIXER_NRDEVICES; i++) | 
|  | 1609 | if (j & mixtable[i].play) | 
|  | 1610 | k |= 1 << i; | 
|  | 1611 | return k; | 
|  | 1612 | } | 
|  | 1613 |  | 
|  | 1614 | static unsigned mixer_recmask(struct cm_state *s) | 
|  | 1615 | { | 
|  | 1616 | unsigned long flags; | 
|  | 1617 | int i, j, k; | 
|  | 1618 |  | 
|  | 1619 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1620 | j = rdmixer(s, DSP_MIX_ADCMIXIDX_L); | 
|  | 1621 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1622 | for (k = i = 0; i < SOUND_MIXER_NRDEVICES; i++) | 
|  | 1623 | if (j & mixtable[i].rec) | 
|  | 1624 | k |= 1 << i; | 
|  | 1625 | return k; | 
|  | 1626 | } | 
|  | 1627 |  | 
|  | 1628 | static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg) | 
|  | 1629 | { | 
|  | 1630 | unsigned long flags; | 
|  | 1631 | int i, val, j; | 
|  | 1632 | unsigned char l, r, rl, rr; | 
|  | 1633 | void __user *argp = (void __user *)arg; | 
|  | 1634 | int __user *p = argp; | 
|  | 1635 |  | 
|  | 1636 | VALIDATE_STATE(s); | 
|  | 1637 | if (cmd == SOUND_MIXER_INFO) { | 
|  | 1638 | mixer_info info; | 
|  | 1639 | memset(&info, 0, sizeof(info)); | 
|  | 1640 | strlcpy(info.id, "cmpci", sizeof(info.id)); | 
|  | 1641 | strlcpy(info.name, "C-Media PCI", sizeof(info.name)); | 
|  | 1642 | info.modify_counter = s->mix.modcnt; | 
|  | 1643 | if (copy_to_user(argp, &info, sizeof(info))) | 
|  | 1644 | return -EFAULT; | 
|  | 1645 | return 0; | 
|  | 1646 | } | 
|  | 1647 | if (cmd == SOUND_OLD_MIXER_INFO) { | 
|  | 1648 | _old_mixer_info info; | 
|  | 1649 | memset(&info, 0, sizeof(info)); | 
|  | 1650 | strlcpy(info.id, "cmpci", sizeof(info.id)); | 
|  | 1651 | strlcpy(info.name, "C-Media cmpci", sizeof(info.name)); | 
|  | 1652 | if (copy_to_user(argp, &info, sizeof(info))) | 
|  | 1653 | return -EFAULT; | 
|  | 1654 | return 0; | 
|  | 1655 | } | 
|  | 1656 | if (cmd == OSS_GETVERSION) | 
|  | 1657 | return put_user(SOUND_VERSION, p); | 
|  | 1658 | if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) | 
|  | 1659 | return -EINVAL; | 
|  | 1660 | if (_SIOC_DIR(cmd) == _SIOC_READ) { | 
|  | 1661 | switch (_IOC_NR(cmd)) { | 
|  | 1662 | case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ | 
|  | 1663 | val = mixer_recmask(s); | 
|  | 1664 | return put_user(val, p); | 
|  | 1665 |  | 
|  | 1666 | case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */ | 
|  | 1667 | val = mixer_outmask(s); | 
|  | 1668 | return put_user(val, p); | 
|  | 1669 |  | 
|  | 1670 | case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ | 
|  | 1671 | for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) | 
|  | 1672 | if (mixtable[i].type) | 
|  | 1673 | val |= 1 << i; | 
|  | 1674 | return put_user(val, p); | 
|  | 1675 |  | 
|  | 1676 | case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ | 
|  | 1677 | for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) | 
|  | 1678 | if (mixtable[i].rec) | 
|  | 1679 | val |= 1 << i; | 
|  | 1680 | return put_user(val, p); | 
|  | 1681 |  | 
|  | 1682 | case SOUND_MIXER_OUTMASK: /* Arg contains a bit for each supported recording source */ | 
|  | 1683 | for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) | 
|  | 1684 | if (mixtable[i].play) | 
|  | 1685 | val |= 1 << i; | 
|  | 1686 | return put_user(val, p); | 
|  | 1687 |  | 
|  | 1688 | case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ | 
|  | 1689 | for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) | 
|  | 1690 | if (mixtable[i].type && mixtable[i].type != MT_4MUTEMONO) | 
|  | 1691 | val |= 1 << i; | 
|  | 1692 | return put_user(val, p); | 
|  | 1693 |  | 
|  | 1694 | case SOUND_MIXER_CAPS: | 
|  | 1695 | return put_user(0, p); | 
|  | 1696 |  | 
|  | 1697 | default: | 
|  | 1698 | i = _IOC_NR(cmd); | 
|  | 1699 | if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type) | 
|  | 1700 | return -EINVAL; | 
|  | 1701 | if (!volidx[i]) | 
|  | 1702 | return -EINVAL; | 
|  | 1703 | return put_user(s->mix.vol[volidx[i]-1], p); | 
|  | 1704 | } | 
|  | 1705 | } | 
|  | 1706 | if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) | 
|  | 1707 | return -EINVAL; | 
|  | 1708 | s->mix.modcnt++; | 
|  | 1709 | switch (_IOC_NR(cmd)) { | 
|  | 1710 | case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ | 
|  | 1711 | if (get_user(val, p)) | 
|  | 1712 | return -EFAULT; | 
|  | 1713 | i = generic_hweight32(val); | 
|  | 1714 | for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) { | 
|  | 1715 | if (!(val & (1 << i))) | 
|  | 1716 | continue; | 
|  | 1717 | if (!mixtable[i].rec) { | 
|  | 1718 | val &= ~(1 << i); | 
|  | 1719 | continue; | 
|  | 1720 | } | 
|  | 1721 | j |= mixtable[i].rec; | 
|  | 1722 | } | 
|  | 1723 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1724 | wrmixer(s, DSP_MIX_ADCMIXIDX_L, j); | 
|  | 1725 | wrmixer(s, DSP_MIX_ADCMIXIDX_R, (j & 1) | (j>>1) | (j & 0x80)); | 
|  | 1726 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1727 | return 0; | 
|  | 1728 |  | 
|  | 1729 | case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */ | 
|  | 1730 | if (get_user(val, p)) | 
|  | 1731 | return -EFAULT; | 
|  | 1732 | for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) { | 
|  | 1733 | if (!(val & (1 << i))) | 
|  | 1734 | continue; | 
|  | 1735 | if (!mixtable[i].play) { | 
|  | 1736 | val &= ~(1 << i); | 
|  | 1737 | continue; | 
|  | 1738 | } | 
|  | 1739 | j |= mixtable[i].play; | 
|  | 1740 | } | 
|  | 1741 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1742 | wrmixer(s, DSP_MIX_OUTMIXIDX, j); | 
|  | 1743 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1744 | return 0; | 
|  | 1745 |  | 
|  | 1746 | default: | 
|  | 1747 | i = _IOC_NR(cmd); | 
|  | 1748 | if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type) | 
|  | 1749 | return -EINVAL; | 
|  | 1750 | if (get_user(val, p)) | 
|  | 1751 | return -EFAULT; | 
|  | 1752 | l = val & 0xff; | 
|  | 1753 | r = (val >> 8) & 0xff; | 
|  | 1754 | if (l > 100) | 
|  | 1755 | l = 100; | 
|  | 1756 | if (r > 100) | 
|  | 1757 | r = 100; | 
|  | 1758 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1759 | switch (mixtable[i].type) { | 
|  | 1760 | case MT_4: | 
|  | 1761 | if (l >= 10) | 
|  | 1762 | l -= 10; | 
|  | 1763 | if (r >= 10) | 
|  | 1764 | r -= 10; | 
|  | 1765 | frobindir(s, mixtable[i].left, 0xf0, l / 6); | 
|  | 1766 | frobindir(s, mixtable[i].right, 0xf0, l / 6); | 
|  | 1767 | break; | 
|  | 1768 |  | 
|  | 1769 | case MT_4MUTEMONO: | 
|  | 1770 | rl = (l < 4 ? 0 : (l - 5) / 3) & 31; | 
|  | 1771 | rr = (rl >> 2) & 7; | 
|  | 1772 | wrmixer(s, mixtable[i].left, rl<<3); | 
|  | 1773 | if (i == SOUND_MIXER_MIC) | 
|  | 1774 | maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1); | 
|  | 1775 | break; | 
|  | 1776 |  | 
|  | 1777 | case MT_5MUTEMONO: | 
|  | 1778 | rl = l < 4 ? 0 : (l - 5) / 3; | 
|  | 1779 | wrmixer(s, mixtable[i].left, rl<<3); | 
|  | 1780 | l = rdmixer(s, DSP_MIX_OUTMIXIDX) & ~mixtable[i].play; | 
|  | 1781 | r = rl ? mixtable[i].play : 0; | 
|  | 1782 | wrmixer(s, DSP_MIX_OUTMIXIDX, l | r); | 
|  | 1783 | /* for recording */ | 
|  | 1784 | if (i == SOUND_MIXER_MIC) { | 
|  | 1785 | if (s->chip_version >= 37) { | 
|  | 1786 | rr = rl >> 1; | 
|  | 1787 | maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, (rr&0x07)<<1); | 
|  | 1788 | frobindir(s, DSP_MIX_EXTENSION, ~0x01, rr>>3); | 
|  | 1789 | } else { | 
|  | 1790 | rr = rl >> 2; | 
|  | 1791 | maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1); | 
|  | 1792 | } | 
|  | 1793 | } | 
|  | 1794 | break; | 
|  | 1795 |  | 
|  | 1796 | case MT_5MUTE: | 
|  | 1797 | rl = l < 4 ? 0 : (l - 5) / 3; | 
|  | 1798 | rr = r < 4 ? 0 : (r - 5) / 3; | 
|  | 1799 | wrmixer(s, mixtable[i].left, rl<<3); | 
|  | 1800 | wrmixer(s, mixtable[i].right, rr<<3); | 
|  | 1801 | l = rdmixer(s, DSP_MIX_OUTMIXIDX); | 
|  | 1802 | l &= ~mixtable[i].play; | 
|  | 1803 | r = (rl|rr) ? mixtable[i].play : 0; | 
|  | 1804 | wrmixer(s, DSP_MIX_OUTMIXIDX, l | r); | 
|  | 1805 | break; | 
|  | 1806 |  | 
|  | 1807 | case MT_6MUTE: | 
|  | 1808 | if (l < 6) | 
|  | 1809 | rl = 0x00; | 
|  | 1810 | else | 
|  | 1811 | rl = l * 2 / 3; | 
|  | 1812 | if (r < 6) | 
|  | 1813 | rr = 0x00; | 
|  | 1814 | else | 
|  | 1815 | rr = r * 2 / 3; | 
|  | 1816 | wrmixer(s, mixtable[i].left, rl); | 
|  | 1817 | wrmixer(s, mixtable[i].right, rr); | 
|  | 1818 | break; | 
|  | 1819 | } | 
|  | 1820 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1821 |  | 
|  | 1822 | if (!volidx[i]) | 
|  | 1823 | return -EINVAL; | 
|  | 1824 | s->mix.vol[volidx[i]-1] = val; | 
|  | 1825 | return put_user(s->mix.vol[volidx[i]-1], p); | 
|  | 1826 | } | 
|  | 1827 | } | 
|  | 1828 |  | 
|  | 1829 | /* --------------------------------------------------------------------- */ | 
|  | 1830 |  | 
|  | 1831 | static int cm_open_mixdev(struct inode *inode, struct file *file) | 
|  | 1832 | { | 
|  | 1833 | int minor = iminor(inode); | 
|  | 1834 | struct list_head *list; | 
|  | 1835 | struct cm_state *s; | 
|  | 1836 |  | 
|  | 1837 | for (list = devs.next; ; list = list->next) { | 
|  | 1838 | if (list == &devs) | 
|  | 1839 | return -ENODEV; | 
|  | 1840 | s = list_entry(list, struct cm_state, devs); | 
|  | 1841 | if (s->dev_mixer == minor) | 
|  | 1842 | break; | 
|  | 1843 | } | 
|  | 1844 | VALIDATE_STATE(s); | 
|  | 1845 | file->private_data = s; | 
|  | 1846 | return nonseekable_open(inode, file); | 
|  | 1847 | } | 
|  | 1848 |  | 
|  | 1849 | static int cm_release_mixdev(struct inode *inode, struct file *file) | 
|  | 1850 | { | 
|  | 1851 | struct cm_state *s = (struct cm_state *)file->private_data; | 
|  | 1852 |  | 
|  | 1853 | VALIDATE_STATE(s); | 
|  | 1854 | return 0; | 
|  | 1855 | } | 
|  | 1856 |  | 
|  | 1857 | static int cm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 
|  | 1858 | { | 
|  | 1859 | return mixer_ioctl((struct cm_state *)file->private_data, cmd, arg); | 
|  | 1860 | } | 
|  | 1861 |  | 
|  | 1862 | static /*const*/ struct file_operations cm_mixer_fops = { | 
|  | 1863 | .owner	 = THIS_MODULE, | 
|  | 1864 | .llseek	 = no_llseek, | 
|  | 1865 | .ioctl	 = cm_ioctl_mixdev, | 
|  | 1866 | .open	 = cm_open_mixdev, | 
|  | 1867 | .release = cm_release_mixdev, | 
|  | 1868 | }; | 
|  | 1869 |  | 
|  | 1870 |  | 
|  | 1871 | /* --------------------------------------------------------------------- */ | 
|  | 1872 |  | 
|  | 1873 | static int drain_dac(struct cm_state *s, int nonblock) | 
|  | 1874 | { | 
|  | 1875 | DECLARE_WAITQUEUE(wait, current); | 
|  | 1876 | unsigned long flags; | 
|  | 1877 | int count, tmo; | 
|  | 1878 |  | 
|  | 1879 | if (s->dma_dac.mapped || !s->dma_dac.ready) | 
|  | 1880 | return 0; | 
|  | 1881 | add_wait_queue(&s->dma_dac.wait, &wait); | 
|  | 1882 | for (;;) { | 
|  | 1883 | __set_current_state(TASK_INTERRUPTIBLE); | 
|  | 1884 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1885 | count = s->dma_dac.count; | 
|  | 1886 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1887 | if (count <= 0) | 
|  | 1888 | break; | 
|  | 1889 | if (signal_pending(current)) | 
|  | 1890 | break; | 
|  | 1891 | if (nonblock) { | 
|  | 1892 | remove_wait_queue(&s->dma_dac.wait, &wait); | 
|  | 1893 | set_current_state(TASK_RUNNING); | 
|  | 1894 | return -EBUSY; | 
|  | 1895 | } | 
|  | 1896 | tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac; | 
|  | 1897 | tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK]; | 
|  | 1898 | if (!schedule_timeout(tmo + 1)) | 
|  | 1899 | DBG(printk(KERN_DEBUG "cmpci: dma timed out??\n");) | 
|  | 1900 | } | 
|  | 1901 | remove_wait_queue(&s->dma_dac.wait, &wait); | 
|  | 1902 | set_current_state(TASK_RUNNING); | 
|  | 1903 | if (signal_pending(current)) | 
|  | 1904 | return -ERESTARTSYS; | 
|  | 1905 | return 0; | 
|  | 1906 | } | 
|  | 1907 |  | 
|  | 1908 | /* --------------------------------------------------------------------- */ | 
|  | 1909 |  | 
|  | 1910 | static ssize_t cm_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 
|  | 1911 | { | 
|  | 1912 | struct cm_state *s = (struct cm_state *)file->private_data; | 
|  | 1913 | DECLARE_WAITQUEUE(wait, current); | 
|  | 1914 | ssize_t ret; | 
|  | 1915 | unsigned long flags; | 
|  | 1916 | unsigned swptr; | 
|  | 1917 | int cnt; | 
|  | 1918 |  | 
|  | 1919 | VALIDATE_STATE(s); | 
|  | 1920 | if (s->dma_adc.mapped) | 
|  | 1921 | return -ENXIO; | 
|  | 1922 | if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) | 
|  | 1923 | return ret; | 
|  | 1924 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 
|  | 1925 | return -EFAULT; | 
|  | 1926 | ret = 0; | 
|  | 1927 |  | 
|  | 1928 | add_wait_queue(&s->dma_adc.wait, &wait); | 
|  | 1929 | while (count > 0) { | 
|  | 1930 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1931 | swptr = s->dma_adc.swptr; | 
|  | 1932 | cnt = s->dma_adc.dmasize-swptr; | 
|  | 1933 | if (s->dma_adc.count < cnt) | 
|  | 1934 | cnt = s->dma_adc.count; | 
|  | 1935 | if (cnt <= 0) | 
|  | 1936 | __set_current_state(TASK_INTERRUPTIBLE); | 
|  | 1937 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1938 | if (cnt > count) | 
|  | 1939 | cnt = count; | 
|  | 1940 | if (cnt <= 0) { | 
|  | 1941 | if (s->dma_adc.enabled) | 
|  | 1942 | start_adc(s); | 
|  | 1943 | if (file->f_flags & O_NONBLOCK) { | 
|  | 1944 | if (!ret) | 
|  | 1945 | ret = -EAGAIN; | 
|  | 1946 | goto out; | 
|  | 1947 | } | 
|  | 1948 | if (!schedule_timeout(HZ)) { | 
|  | 1949 | printk(KERN_DEBUG "cmpci: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", | 
|  | 1950 | s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, | 
|  | 1951 | s->dma_adc.hwptr, s->dma_adc.swptr); | 
|  | 1952 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1953 | stop_adc_unlocked(s); | 
|  | 1954 | set_dmaadc(s, s->dma_adc.dmaaddr, s->dma_adc.dmasamples); | 
|  | 1955 | /* program sample counts */ | 
|  | 1956 | set_countadc(s, s->dma_adc.fragsamples); | 
|  | 1957 | s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0; | 
|  | 1958 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 1959 | } | 
|  | 1960 | if (signal_pending(current)) { | 
|  | 1961 | if (!ret) | 
|  | 1962 | ret = -ERESTARTSYS; | 
|  | 1963 | goto out; | 
|  | 1964 | } | 
|  | 1965 | continue; | 
|  | 1966 | } | 
|  | 1967 | if (s->status & DO_BIGENDIAN_R) { | 
|  | 1968 | int	i, err; | 
|  | 1969 | unsigned char *src; | 
|  | 1970 | char __user *dst = buffer; | 
|  | 1971 | unsigned char data[2]; | 
|  | 1972 |  | 
|  | 1973 | src = (unsigned char *) (s->dma_adc.rawbuf + swptr); | 
|  | 1974 | // copy left/right sample at one time | 
|  | 1975 | for (i = 0; i < cnt / 2; i++) { | 
|  | 1976 | data[0] = src[1]; | 
|  | 1977 | data[1] = src[0]; | 
|  | 1978 | if ((err = __put_user(data[0], dst++))) { | 
|  | 1979 | ret = err; | 
|  | 1980 | goto out; | 
|  | 1981 | } | 
|  | 1982 | if ((err = __put_user(data[1], dst++))) { | 
|  | 1983 | ret = err; | 
|  | 1984 | goto out; | 
|  | 1985 | } | 
|  | 1986 | src += 2; | 
|  | 1987 | } | 
|  | 1988 | } else if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) { | 
|  | 1989 | if (!ret) | 
|  | 1990 | ret = -EFAULT; | 
|  | 1991 | goto out; | 
|  | 1992 | } | 
|  | 1993 | swptr = (swptr + cnt) % s->dma_adc.dmasize; | 
|  | 1994 | spin_lock_irqsave(&s->lock, flags); | 
|  | 1995 | s->dma_adc.swptr = swptr; | 
|  | 1996 | s->dma_adc.count -= cnt; | 
|  | 1997 | count -= cnt; | 
|  | 1998 | buffer += cnt; | 
|  | 1999 | ret += cnt; | 
|  | 2000 | if (s->dma_adc.enabled) | 
|  | 2001 | start_adc_unlocked(s); | 
|  | 2002 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2003 | } | 
|  | 2004 | out: | 
|  | 2005 | remove_wait_queue(&s->dma_adc.wait, &wait); | 
|  | 2006 | set_current_state(TASK_RUNNING); | 
|  | 2007 | return ret; | 
|  | 2008 | } | 
|  | 2009 |  | 
|  | 2010 | static ssize_t cm_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 
|  | 2011 | { | 
|  | 2012 | struct cm_state *s = (struct cm_state *)file->private_data; | 
|  | 2013 | DECLARE_WAITQUEUE(wait, current); | 
|  | 2014 | ssize_t ret; | 
|  | 2015 | unsigned long flags; | 
|  | 2016 | unsigned swptr; | 
|  | 2017 | int cnt; | 
|  | 2018 |  | 
|  | 2019 | VALIDATE_STATE(s); | 
|  | 2020 | if (s->dma_dac.mapped) | 
|  | 2021 | return -ENXIO; | 
|  | 2022 | if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) | 
|  | 2023 | return ret; | 
|  | 2024 | if (!access_ok(VERIFY_READ, buffer, count)) | 
|  | 2025 | return -EFAULT; | 
|  | 2026 | if (s->status & DO_DUAL_DAC) { | 
|  | 2027 | if (s->dma_adc.mapped) | 
|  | 2028 | return -ENXIO; | 
|  | 2029 | if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) | 
|  | 2030 | return ret; | 
|  | 2031 | } | 
|  | 2032 | if (!access_ok(VERIFY_READ, buffer, count)) | 
|  | 2033 | return -EFAULT; | 
|  | 2034 | ret = 0; | 
|  | 2035 |  | 
|  | 2036 | add_wait_queue(&s->dma_dac.wait, &wait); | 
|  | 2037 | while (count > 0) { | 
|  | 2038 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2039 | if (s->dma_dac.count < 0) { | 
|  | 2040 | s->dma_dac.count = 0; | 
|  | 2041 | s->dma_dac.swptr = s->dma_dac.hwptr; | 
|  | 2042 | } | 
|  | 2043 | if (s->status & DO_DUAL_DAC) { | 
|  | 2044 | s->dma_adc.swptr = s->dma_dac.swptr; | 
|  | 2045 | s->dma_adc.count = s->dma_dac.count; | 
|  | 2046 | s->dma_adc.endcleared = s->dma_dac.endcleared; | 
|  | 2047 | } | 
|  | 2048 | swptr = s->dma_dac.swptr; | 
|  | 2049 | cnt = s->dma_dac.dmasize-swptr; | 
|  | 2050 | if (s->status & DO_AC3_SW) { | 
|  | 2051 | if (s->dma_dac.count + 2 * cnt > s->dma_dac.dmasize) | 
|  | 2052 | cnt = (s->dma_dac.dmasize - s->dma_dac.count) / 2; | 
|  | 2053 | } else { | 
|  | 2054 | if (s->dma_dac.count + cnt > s->dma_dac.dmasize) | 
|  | 2055 | cnt = s->dma_dac.dmasize - s->dma_dac.count; | 
|  | 2056 | } | 
|  | 2057 | if (cnt <= 0) | 
|  | 2058 | __set_current_state(TASK_INTERRUPTIBLE); | 
|  | 2059 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2060 | if (cnt > count) | 
|  | 2061 | cnt = count; | 
|  | 2062 | if ((s->status & DO_DUAL_DAC) && (cnt > count / 2)) | 
|  | 2063 | cnt = count / 2; | 
|  | 2064 | if (cnt <= 0) { | 
|  | 2065 | if (s->dma_dac.enabled) | 
|  | 2066 | start_dac(s); | 
|  | 2067 | if (file->f_flags & O_NONBLOCK) { | 
|  | 2068 | if (!ret) | 
|  | 2069 | ret = -EAGAIN; | 
|  | 2070 | goto out; | 
|  | 2071 | } | 
|  | 2072 | if (!schedule_timeout(HZ)) { | 
|  | 2073 | printk(KERN_DEBUG "cmpci: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", | 
|  | 2074 | s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, | 
|  | 2075 | s->dma_dac.hwptr, s->dma_dac.swptr); | 
|  | 2076 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2077 | stop_dac_unlocked(s); | 
|  | 2078 | set_dmadac(s, s->dma_dac.dmaaddr, s->dma_dac.dmasamples); | 
|  | 2079 | /* program sample counts */ | 
|  | 2080 | set_countdac(s, s->dma_dac.fragsamples); | 
|  | 2081 | s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0; | 
|  | 2082 | if (s->status & DO_DUAL_DAC)  { | 
|  | 2083 | set_dmadac1(s, s->dma_adc.dmaaddr, s->dma_adc.dmasamples); | 
|  | 2084 | s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0; | 
|  | 2085 | } | 
|  | 2086 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2087 | } | 
|  | 2088 | if (signal_pending(current)) { | 
|  | 2089 | if (!ret) | 
|  | 2090 | ret = -ERESTARTSYS; | 
|  | 2091 | goto out; | 
|  | 2092 | } | 
|  | 2093 | continue; | 
|  | 2094 | } | 
|  | 2095 | if (s->status & DO_AC3_SW) { | 
|  | 2096 | int err; | 
|  | 2097 |  | 
|  | 2098 | // clip exceeded data, caught by 033 and 037 | 
|  | 2099 | if (swptr + 2 * cnt > s->dma_dac.dmasize) | 
|  | 2100 | cnt = (s->dma_dac.dmasize - swptr) / 2; | 
|  | 2101 | if ((err = trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt))) { | 
|  | 2102 | ret = err; | 
|  | 2103 | goto out; | 
|  | 2104 | } | 
|  | 2105 | swptr = (swptr + 2 * cnt) % s->dma_dac.dmasize; | 
|  | 2106 | } else if ((s->status & DO_DUAL_DAC) && (s->status & DO_BIGENDIAN_W)) { | 
|  | 2107 | int	i, err; | 
|  | 2108 | const char __user *src = buffer; | 
|  | 2109 | unsigned char *dst0, *dst1; | 
|  | 2110 | unsigned char data[8]; | 
|  | 2111 |  | 
|  | 2112 | dst0 = (unsigned char *) (s->dma_dac.rawbuf + swptr); | 
|  | 2113 | dst1 = (unsigned char *) (s->dma_adc.rawbuf + swptr); | 
|  | 2114 | // copy left/right sample at one time | 
|  | 2115 | for (i = 0; i < cnt / 4; i++) { | 
|  | 2116 | if ((err = __get_user(data[0], src++))) { | 
|  | 2117 | ret = err; | 
|  | 2118 | goto out; | 
|  | 2119 | } | 
|  | 2120 | if ((err = __get_user(data[1], src++))) { | 
|  | 2121 | ret = err; | 
|  | 2122 | goto out; | 
|  | 2123 | } | 
|  | 2124 | if ((err = __get_user(data[2], src++))) { | 
|  | 2125 | ret = err; | 
|  | 2126 | goto out; | 
|  | 2127 | } | 
|  | 2128 | if ((err = __get_user(data[3], src++))) { | 
|  | 2129 | ret = err; | 
|  | 2130 | goto out; | 
|  | 2131 | } | 
|  | 2132 | if ((err = __get_user(data[4], src++))) { | 
|  | 2133 | ret = err; | 
|  | 2134 | goto out; | 
|  | 2135 | } | 
|  | 2136 | if ((err = __get_user(data[5], src++))) { | 
|  | 2137 | ret = err; | 
|  | 2138 | goto out; | 
|  | 2139 | } | 
|  | 2140 | if ((err = __get_user(data[6], src++))) { | 
|  | 2141 | ret = err; | 
|  | 2142 | goto out; | 
|  | 2143 | } | 
|  | 2144 | if ((err = __get_user(data[7], src++))) { | 
|  | 2145 | ret = err; | 
|  | 2146 | goto out; | 
|  | 2147 | } | 
|  | 2148 | dst0[0] = data[1]; | 
|  | 2149 | dst0[1] = data[0]; | 
|  | 2150 | dst0[2] = data[3]; | 
|  | 2151 | dst0[3] = data[2]; | 
|  | 2152 | dst1[0] = data[5]; | 
|  | 2153 | dst1[1] = data[4]; | 
|  | 2154 | dst1[2] = data[7]; | 
|  | 2155 | dst1[3] = data[6]; | 
|  | 2156 | dst0 += 4; | 
|  | 2157 | dst1 += 4; | 
|  | 2158 | } | 
|  | 2159 | swptr = (swptr + cnt) % s->dma_dac.dmasize; | 
|  | 2160 | } else if (s->status & DO_DUAL_DAC) { | 
|  | 2161 | int	i, err; | 
|  | 2162 | unsigned long __user *src = (unsigned long __user *) buffer; | 
|  | 2163 | unsigned long *dst0, *dst1; | 
|  | 2164 |  | 
|  | 2165 | dst0 = (unsigned long *) (s->dma_dac.rawbuf + swptr); | 
|  | 2166 | dst1 = (unsigned long *) (s->dma_adc.rawbuf + swptr); | 
|  | 2167 | // copy left/right sample at one time | 
|  | 2168 | for (i = 0; i < cnt / 4; i++) { | 
|  | 2169 | if ((err = __get_user(*dst0++, src++))) { | 
|  | 2170 | ret = err; | 
|  | 2171 | goto out; | 
|  | 2172 | } | 
|  | 2173 | if ((err = __get_user(*dst1++, src++))) { | 
|  | 2174 | ret = err; | 
|  | 2175 | goto out; | 
|  | 2176 | } | 
|  | 2177 | } | 
|  | 2178 | swptr = (swptr + cnt) % s->dma_dac.dmasize; | 
|  | 2179 | } else if (s->status & DO_BIGENDIAN_W) { | 
|  | 2180 | int	i, err; | 
|  | 2181 | const char __user *src = buffer; | 
|  | 2182 | unsigned char *dst; | 
|  | 2183 | unsigned char data[2]; | 
|  | 2184 |  | 
|  | 2185 | dst = (unsigned char *) (s->dma_dac.rawbuf + swptr); | 
|  | 2186 | // swap hi/lo bytes for each sample | 
|  | 2187 | for (i = 0; i < cnt / 2; i++) { | 
|  | 2188 | if ((err = __get_user(data[0], src++))) { | 
|  | 2189 | ret = err; | 
|  | 2190 | goto out; | 
|  | 2191 | } | 
|  | 2192 | if ((err = __get_user(data[1], src++))) { | 
|  | 2193 | ret = err; | 
|  | 2194 | goto out; | 
|  | 2195 | } | 
|  | 2196 | dst[0] = data[1]; | 
|  | 2197 | dst[1] = data[0]; | 
|  | 2198 | dst += 2; | 
|  | 2199 | } | 
|  | 2200 | swptr = (swptr + cnt) % s->dma_dac.dmasize; | 
|  | 2201 | } else { | 
|  | 2202 | if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) { | 
|  | 2203 | if (!ret) | 
|  | 2204 | ret = -EFAULT; | 
|  | 2205 | goto out; | 
|  | 2206 | } | 
|  | 2207 | swptr = (swptr + cnt) % s->dma_dac.dmasize; | 
|  | 2208 | } | 
|  | 2209 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2210 | s->dma_dac.swptr = swptr; | 
|  | 2211 | s->dma_dac.count += cnt; | 
|  | 2212 | if (s->status & DO_AC3_SW) | 
|  | 2213 | s->dma_dac.count += cnt; | 
|  | 2214 | s->dma_dac.endcleared = 0; | 
|  | 2215 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2216 | count -= cnt; | 
|  | 2217 | buffer += cnt; | 
|  | 2218 | ret += cnt; | 
|  | 2219 | if (s->status & DO_DUAL_DAC) { | 
|  | 2220 | count -= cnt; | 
|  | 2221 | buffer += cnt; | 
|  | 2222 | ret += cnt; | 
|  | 2223 | } | 
|  | 2224 | if (s->dma_dac.enabled) | 
|  | 2225 | start_dac(s); | 
|  | 2226 | } | 
|  | 2227 | out: | 
|  | 2228 | remove_wait_queue(&s->dma_dac.wait, &wait); | 
|  | 2229 | set_current_state(TASK_RUNNING); | 
|  | 2230 | return ret; | 
|  | 2231 | } | 
|  | 2232 |  | 
|  | 2233 | static unsigned int cm_poll(struct file *file, struct poll_table_struct *wait) | 
|  | 2234 | { | 
|  | 2235 | struct cm_state *s = (struct cm_state *)file->private_data; | 
|  | 2236 | unsigned long flags; | 
|  | 2237 | unsigned int mask = 0; | 
|  | 2238 |  | 
|  | 2239 | VALIDATE_STATE(s); | 
|  | 2240 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2241 | if (!s->dma_dac.ready && prog_dmabuf(s, 0)) | 
|  | 2242 | return 0; | 
|  | 2243 | poll_wait(file, &s->dma_dac.wait, wait); | 
|  | 2244 | } | 
|  | 2245 | if (file->f_mode & FMODE_READ) { | 
|  | 2246 | if (!s->dma_adc.ready && prog_dmabuf(s, 1)) | 
|  | 2247 | return 0; | 
|  | 2248 | poll_wait(file, &s->dma_adc.wait, wait); | 
|  | 2249 | } | 
|  | 2250 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2251 | cm_update_ptr(s); | 
|  | 2252 | if (file->f_mode & FMODE_READ) { | 
|  | 2253 | if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) | 
|  | 2254 | mask |= POLLIN | POLLRDNORM; | 
|  | 2255 | } | 
|  | 2256 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2257 | if (s->dma_dac.mapped) { | 
|  | 2258 | if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) | 
|  | 2259 | mask |= POLLOUT | POLLWRNORM; | 
|  | 2260 | } else { | 
|  | 2261 | if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize) | 
|  | 2262 | mask |= POLLOUT | POLLWRNORM; | 
|  | 2263 | } | 
|  | 2264 | } | 
|  | 2265 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2266 | return mask; | 
|  | 2267 | } | 
|  | 2268 |  | 
|  | 2269 | static int cm_mmap(struct file *file, struct vm_area_struct *vma) | 
|  | 2270 | { | 
|  | 2271 | struct cm_state *s = (struct cm_state *)file->private_data; | 
|  | 2272 | struct dmabuf *db; | 
|  | 2273 | int ret = -EINVAL; | 
|  | 2274 | unsigned long size; | 
|  | 2275 |  | 
|  | 2276 | VALIDATE_STATE(s); | 
|  | 2277 | lock_kernel(); | 
|  | 2278 | if (vma->vm_flags & VM_WRITE) { | 
|  | 2279 | if ((ret = prog_dmabuf(s, 0)) != 0) | 
|  | 2280 | goto out; | 
|  | 2281 | db = &s->dma_dac; | 
|  | 2282 | } else if (vma->vm_flags & VM_READ) { | 
|  | 2283 | if ((ret = prog_dmabuf(s, 1)) != 0) | 
|  | 2284 | goto out; | 
|  | 2285 | db = &s->dma_adc; | 
|  | 2286 | } else | 
|  | 2287 | goto out; | 
|  | 2288 | ret = -EINVAL; | 
|  | 2289 | if (vma->vm_pgoff != 0) | 
|  | 2290 | goto out; | 
|  | 2291 | size = vma->vm_end - vma->vm_start; | 
|  | 2292 | if (size > (PAGE_SIZE << db->buforder)) | 
|  | 2293 | goto out; | 
|  | 2294 | ret = -EINVAL; | 
|  | 2295 | if (remap_pfn_range(vma, vma->vm_start, | 
|  | 2296 | virt_to_phys(db->rawbuf) >> PAGE_SHIFT, | 
|  | 2297 | size, vma->vm_page_prot)) | 
|  | 2298 | goto out; | 
|  | 2299 | db->mapped = 1; | 
|  | 2300 | ret = 0; | 
|  | 2301 | out: | 
|  | 2302 | unlock_kernel(); | 
|  | 2303 | return ret; | 
|  | 2304 | } | 
|  | 2305 |  | 
|  | 2306 | #define SNDCTL_SPDIF_COPYRIGHT	_SIOW('S',  0, int)       // set/reset S/PDIF copy protection | 
|  | 2307 | #define SNDCTL_SPDIF_LOOP	_SIOW('S',  1, int)       // set/reset S/PDIF loop | 
|  | 2308 | #define SNDCTL_SPDIF_MONITOR	_SIOW('S',  2, int)       // set S/PDIF monitor | 
|  | 2309 | #define SNDCTL_SPDIF_LEVEL	_SIOW('S',  3, int)       // set/reset S/PDIF out level | 
|  | 2310 | #define SNDCTL_SPDIF_INV	_SIOW('S',  4, int)       // set/reset S/PDIF in inverse | 
|  | 2311 | #define SNDCTL_SPDIF_SEL2	_SIOW('S',  5, int)       // set S/PDIF in #2 | 
|  | 2312 | #define SNDCTL_SPDIF_VALID	_SIOW('S',  6, int)       // set S/PDIF valid | 
|  | 2313 | #define SNDCTL_SPDIFOUT		_SIOW('S',  7, int)       // set S/PDIF out | 
|  | 2314 | #define SNDCTL_SPDIFIN		_SIOW('S',  8, int)       // set S/PDIF out | 
|  | 2315 |  | 
|  | 2316 | static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 
|  | 2317 | { | 
|  | 2318 | struct cm_state *s = (struct cm_state *)file->private_data; | 
|  | 2319 | unsigned long flags; | 
|  | 2320 | audio_buf_info abinfo; | 
|  | 2321 | count_info cinfo; | 
|  | 2322 | int val, mapped, ret; | 
|  | 2323 | unsigned char fmtm, fmtd; | 
|  | 2324 | void __user *argp = (void __user *)arg; | 
|  | 2325 | int __user *p = argp; | 
|  | 2326 |  | 
|  | 2327 | VALIDATE_STATE(s); | 
|  | 2328 | mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || | 
|  | 2329 | ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); | 
|  | 2330 | switch (cmd) { | 
|  | 2331 | case OSS_GETVERSION: | 
|  | 2332 | return put_user(SOUND_VERSION, p); | 
|  | 2333 |  | 
|  | 2334 | case SNDCTL_DSP_SYNC: | 
|  | 2335 | if (file->f_mode & FMODE_WRITE) | 
|  | 2336 | return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/); | 
|  | 2337 | return 0; | 
|  | 2338 |  | 
|  | 2339 | case SNDCTL_DSP_SETDUPLEX: | 
|  | 2340 | return 0; | 
|  | 2341 |  | 
|  | 2342 | case SNDCTL_DSP_GETCAPS: | 
|  | 2343 | return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_BIND, p); | 
|  | 2344 |  | 
|  | 2345 | case SNDCTL_DSP_RESET: | 
|  | 2346 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2347 | stop_dac(s); | 
|  | 2348 | synchronize_irq(s->irq); | 
|  | 2349 | s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0; | 
|  | 2350 | if (s->status & DO_DUAL_DAC) | 
|  | 2351 | s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; | 
|  | 2352 | } | 
|  | 2353 | if (file->f_mode & FMODE_READ) { | 
|  | 2354 | stop_adc(s); | 
|  | 2355 | synchronize_irq(s->irq); | 
|  | 2356 | s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; | 
|  | 2357 | } | 
|  | 2358 | return 0; | 
|  | 2359 |  | 
|  | 2360 | case SNDCTL_DSP_SPEED: | 
|  | 2361 | if (get_user(val, p)) | 
|  | 2362 | return -EFAULT; | 
|  | 2363 | if (val >= 0) { | 
|  | 2364 | if (file->f_mode & FMODE_READ) { | 
|  | 2365 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2366 | stop_adc_unlocked(s); | 
|  | 2367 | s->dma_adc.ready = 0; | 
|  | 2368 | set_adc_rate_unlocked(s, val); | 
|  | 2369 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2370 | } | 
|  | 2371 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2372 | stop_dac(s); | 
|  | 2373 | s->dma_dac.ready = 0; | 
|  | 2374 | if (s->status & DO_DUAL_DAC) | 
|  | 2375 | s->dma_adc.ready = 0; | 
|  | 2376 | set_dac_rate(s, val); | 
|  | 2377 | } | 
|  | 2378 | } | 
|  | 2379 | return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, p); | 
|  | 2380 |  | 
|  | 2381 | case SNDCTL_DSP_STEREO: | 
|  | 2382 | if (get_user(val, p)) | 
|  | 2383 | return -EFAULT; | 
|  | 2384 | fmtd = 0; | 
|  | 2385 | fmtm = ~0; | 
|  | 2386 | if (file->f_mode & FMODE_READ) { | 
|  | 2387 | stop_adc(s); | 
|  | 2388 | s->dma_adc.ready = 0; | 
|  | 2389 | if (val) | 
|  | 2390 | fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; | 
|  | 2391 | else | 
|  | 2392 | fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); | 
|  | 2393 | } | 
|  | 2394 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2395 | stop_dac(s); | 
|  | 2396 | s->dma_dac.ready = 0; | 
|  | 2397 | if (val) | 
|  | 2398 | fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; | 
|  | 2399 | else | 
|  | 2400 | fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT); | 
|  | 2401 | if (s->status & DO_DUAL_DAC) { | 
|  | 2402 | s->dma_adc.ready = 0; | 
|  | 2403 | if (val) | 
|  | 2404 | fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; | 
|  | 2405 | else | 
|  | 2406 | fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); | 
|  | 2407 | } | 
|  | 2408 | } | 
|  | 2409 | set_fmt(s, fmtm, fmtd); | 
|  | 2410 | return 0; | 
|  | 2411 |  | 
|  | 2412 | case SNDCTL_DSP_CHANNELS: | 
|  | 2413 | if (get_user(val, p)) | 
|  | 2414 | return -EFAULT; | 
|  | 2415 | if (val != 0) { | 
|  | 2416 | fmtd = 0; | 
|  | 2417 | fmtm = ~0; | 
|  | 2418 | if (file->f_mode & FMODE_READ) { | 
|  | 2419 | stop_adc(s); | 
|  | 2420 | s->dma_adc.ready = 0; | 
|  | 2421 | if (val >= 2) | 
|  | 2422 | fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; | 
|  | 2423 | else | 
|  | 2424 | fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); | 
|  | 2425 | } | 
|  | 2426 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2427 | stop_dac(s); | 
|  | 2428 | s->dma_dac.ready = 0; | 
|  | 2429 | if (val >= 2) | 
|  | 2430 | fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; | 
|  | 2431 | else | 
|  | 2432 | fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT); | 
|  | 2433 | if (s->status & DO_DUAL_DAC) { | 
|  | 2434 | s->dma_adc.ready = 0; | 
|  | 2435 | if (val >= 2) | 
|  | 2436 | fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; | 
|  | 2437 | else | 
|  | 2438 | fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); | 
|  | 2439 | } | 
|  | 2440 | } | 
|  | 2441 | set_fmt(s, fmtm, fmtd); | 
|  | 2442 | if ((s->capability & CAN_MULTI_CH) | 
|  | 2443 | && (file->f_mode & FMODE_WRITE)) { | 
|  | 2444 | val = set_dac_channels(s, val); | 
|  | 2445 | return put_user(val, p); | 
|  | 2446 | } | 
|  | 2447 | } | 
|  | 2448 | return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) | 
|  | 2449 | : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, p); | 
|  | 2450 |  | 
|  | 2451 | case SNDCTL_DSP_GETFMTS: /* Returns a mask */ | 
|  | 2452 | return put_user(AFMT_S16_BE|AFMT_S16_LE|AFMT_U8| | 
|  | 2453 | ((s->capability & CAN_AC3) ? AFMT_AC3 : 0), p); | 
|  | 2454 |  | 
|  | 2455 | case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ | 
|  | 2456 | if (get_user(val, p)) | 
|  | 2457 | return -EFAULT; | 
|  | 2458 | if (val != AFMT_QUERY) { | 
|  | 2459 | fmtd = 0; | 
|  | 2460 | fmtm = ~0; | 
|  | 2461 | if (file->f_mode & FMODE_READ) { | 
|  | 2462 | stop_adc(s); | 
|  | 2463 | s->dma_adc.ready = 0; | 
|  | 2464 | if (val == AFMT_S16_BE || val == AFMT_S16_LE) | 
|  | 2465 | fmtd |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT; | 
|  | 2466 | else | 
|  | 2467 | fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_ADCSHIFT); | 
|  | 2468 | if (val == AFMT_S16_BE) | 
|  | 2469 | s->status |= DO_BIGENDIAN_R; | 
|  | 2470 | else | 
|  | 2471 | s->status &= ~DO_BIGENDIAN_R; | 
|  | 2472 | } | 
|  | 2473 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2474 | stop_dac(s); | 
|  | 2475 | s->dma_dac.ready = 0; | 
|  | 2476 | if (val == AFMT_S16_BE || val == AFMT_S16_LE || val == AFMT_AC3) | 
|  | 2477 | fmtd |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; | 
|  | 2478 | else | 
|  | 2479 | fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_DACSHIFT); | 
|  | 2480 | if (val == AFMT_AC3) { | 
|  | 2481 | fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; | 
|  | 2482 | set_ac3(s, 48000); | 
|  | 2483 | } else | 
|  | 2484 | set_ac3(s, 0); | 
|  | 2485 | if (s->status & DO_DUAL_DAC) { | 
|  | 2486 | s->dma_adc.ready = 0; | 
|  | 2487 | if (val == AFMT_S16_BE || val == AFMT_S16_LE) | 
|  | 2488 | fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; | 
|  | 2489 | else | 
|  | 2490 | fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); | 
|  | 2491 | } | 
|  | 2492 | if (val == AFMT_S16_BE) | 
|  | 2493 | s->status |= DO_BIGENDIAN_W; | 
|  | 2494 | else | 
|  | 2495 | s->status &= ~DO_BIGENDIAN_W; | 
|  | 2496 | } | 
|  | 2497 | set_fmt(s, fmtm, fmtd); | 
|  | 2498 | } | 
|  | 2499 | if (s->status & DO_AC3) return put_user(AFMT_AC3, p); | 
|  | 2500 | return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) | 
|  | 2501 | : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? val : AFMT_U8, p); | 
|  | 2502 |  | 
|  | 2503 | case SNDCTL_DSP_POST: | 
|  | 2504 | return 0; | 
|  | 2505 |  | 
|  | 2506 | case SNDCTL_DSP_GETTRIGGER: | 
|  | 2507 | val = 0; | 
|  | 2508 | if (s->status & DO_DUAL_DAC) { | 
|  | 2509 | if (file->f_mode & FMODE_WRITE && | 
|  | 2510 | (s->enable & ENDAC) && | 
|  | 2511 | (s->enable & ENADC)) | 
|  | 2512 | val |= PCM_ENABLE_OUTPUT; | 
|  | 2513 | return put_user(val, p); | 
|  | 2514 | } | 
|  | 2515 | if (file->f_mode & FMODE_READ && s->enable & ENADC) | 
|  | 2516 | val |= PCM_ENABLE_INPUT; | 
|  | 2517 | if (file->f_mode & FMODE_WRITE && s->enable & ENDAC) | 
|  | 2518 | val |= PCM_ENABLE_OUTPUT; | 
|  | 2519 | return put_user(val, p); | 
|  | 2520 |  | 
|  | 2521 | case SNDCTL_DSP_SETTRIGGER: | 
|  | 2522 | if (get_user(val, p)) | 
|  | 2523 | return -EFAULT; | 
|  | 2524 | if (file->f_mode & FMODE_READ) { | 
|  | 2525 | if (val & PCM_ENABLE_INPUT) { | 
|  | 2526 | if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) | 
|  | 2527 | return ret; | 
|  | 2528 | s->dma_adc.enabled = 1; | 
|  | 2529 | start_adc(s); | 
|  | 2530 | } else { | 
|  | 2531 | s->dma_adc.enabled = 0; | 
|  | 2532 | stop_adc(s); | 
|  | 2533 | } | 
|  | 2534 | } | 
|  | 2535 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2536 | if (val & PCM_ENABLE_OUTPUT) { | 
|  | 2537 | if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) | 
|  | 2538 | return ret; | 
|  | 2539 | if (s->status & DO_DUAL_DAC) { | 
|  | 2540 | if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) | 
|  | 2541 | return ret; | 
|  | 2542 | } | 
|  | 2543 | s->dma_dac.enabled = 1; | 
|  | 2544 | start_dac(s); | 
|  | 2545 | } else { | 
|  | 2546 | s->dma_dac.enabled = 0; | 
|  | 2547 | stop_dac(s); | 
|  | 2548 | } | 
|  | 2549 | } | 
|  | 2550 | return 0; | 
|  | 2551 |  | 
|  | 2552 | case SNDCTL_DSP_GETOSPACE: | 
|  | 2553 | if (!(file->f_mode & FMODE_WRITE)) | 
|  | 2554 | return -EINVAL; | 
|  | 2555 | if (!(s->enable & ENDAC) && (val = prog_dmabuf(s, 0)) != 0) | 
|  | 2556 | return val; | 
|  | 2557 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2558 | cm_update_ptr(s); | 
|  | 2559 | abinfo.fragsize = s->dma_dac.fragsize; | 
|  | 2560 | abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; | 
|  | 2561 | abinfo.fragstotal = s->dma_dac.numfrag; | 
|  | 2562 | abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; | 
|  | 2563 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2564 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 
|  | 2565 |  | 
|  | 2566 | case SNDCTL_DSP_GETISPACE: | 
|  | 2567 | if (!(file->f_mode & FMODE_READ)) | 
|  | 2568 | return -EINVAL; | 
|  | 2569 | if (!(s->enable & ENADC) && (val = prog_dmabuf(s, 1)) != 0) | 
|  | 2570 | return val; | 
|  | 2571 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2572 | cm_update_ptr(s); | 
|  | 2573 | abinfo.fragsize = s->dma_adc.fragsize; | 
|  | 2574 | abinfo.bytes = s->dma_adc.count; | 
|  | 2575 | abinfo.fragstotal = s->dma_adc.numfrag; | 
|  | 2576 | abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; | 
|  | 2577 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2578 | return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; | 
|  | 2579 |  | 
|  | 2580 | case SNDCTL_DSP_NONBLOCK: | 
|  | 2581 | file->f_flags |= O_NONBLOCK; | 
|  | 2582 | return 0; | 
|  | 2583 |  | 
|  | 2584 | case SNDCTL_DSP_GETODELAY: | 
|  | 2585 | if (!(file->f_mode & FMODE_WRITE)) | 
|  | 2586 | return -EINVAL; | 
|  | 2587 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2588 | cm_update_ptr(s); | 
|  | 2589 | val = s->dma_dac.count; | 
|  | 2590 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2591 | return put_user(val, p); | 
|  | 2592 |  | 
|  | 2593 | case SNDCTL_DSP_GETIPTR: | 
|  | 2594 | if (!(file->f_mode & FMODE_READ)) | 
|  | 2595 | return -EINVAL; | 
|  | 2596 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2597 | cm_update_ptr(s); | 
|  | 2598 | cinfo.bytes = s->dma_adc.total_bytes; | 
|  | 2599 | cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; | 
|  | 2600 | cinfo.ptr = s->dma_adc.hwptr; | 
|  | 2601 | if (s->dma_adc.mapped) | 
|  | 2602 | s->dma_adc.count &= s->dma_adc.fragsize-1; | 
|  | 2603 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2604 | return copy_to_user(argp, &cinfo, sizeof(cinfo))  ? -EFAULT : 0; | 
|  | 2605 |  | 
|  | 2606 | case SNDCTL_DSP_GETOPTR: | 
|  | 2607 | if (!(file->f_mode & FMODE_WRITE)) | 
|  | 2608 | return -EINVAL; | 
|  | 2609 | spin_lock_irqsave(&s->lock, flags); | 
|  | 2610 | cm_update_ptr(s); | 
|  | 2611 | cinfo.bytes = s->dma_dac.total_bytes; | 
|  | 2612 | cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; | 
|  | 2613 | cinfo.ptr = s->dma_dac.hwptr; | 
|  | 2614 | if (s->dma_dac.mapped) | 
|  | 2615 | s->dma_dac.count &= s->dma_dac.fragsize-1; | 
|  | 2616 | if (s->status & DO_DUAL_DAC) { | 
|  | 2617 | if (s->dma_adc.mapped) | 
|  | 2618 | s->dma_adc.count &= s->dma_adc.fragsize-1; | 
|  | 2619 | } | 
|  | 2620 | spin_unlock_irqrestore(&s->lock, flags); | 
|  | 2621 | return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; | 
|  | 2622 |  | 
|  | 2623 | case SNDCTL_DSP_GETBLKSIZE: | 
|  | 2624 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2625 | if ((val = prog_dmabuf(s, 0))) | 
|  | 2626 | return val; | 
|  | 2627 | if (s->status & DO_DUAL_DAC) { | 
|  | 2628 | if ((val = prog_dmabuf(s, 1))) | 
|  | 2629 | return val; | 
|  | 2630 | return put_user(2 * s->dma_dac.fragsize, p); | 
|  | 2631 | } | 
|  | 2632 | return put_user(s->dma_dac.fragsize, p); | 
|  | 2633 | } | 
|  | 2634 | if ((val = prog_dmabuf(s, 1))) | 
|  | 2635 | return val; | 
|  | 2636 | return put_user(s->dma_adc.fragsize, p); | 
|  | 2637 |  | 
|  | 2638 | case SNDCTL_DSP_SETFRAGMENT: | 
|  | 2639 | if (get_user(val, p)) | 
|  | 2640 | return -EFAULT; | 
|  | 2641 | if (file->f_mode & FMODE_READ) { | 
|  | 2642 | s->dma_adc.ossfragshift = val & 0xffff; | 
|  | 2643 | s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; | 
|  | 2644 | if (s->dma_adc.ossfragshift < 4) | 
|  | 2645 | s->dma_adc.ossfragshift = 4; | 
|  | 2646 | if (s->dma_adc.ossfragshift > 15) | 
|  | 2647 | s->dma_adc.ossfragshift = 15; | 
|  | 2648 | if (s->dma_adc.ossmaxfrags < 4) | 
|  | 2649 | s->dma_adc.ossmaxfrags = 4; | 
|  | 2650 | } | 
|  | 2651 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2652 | s->dma_dac.ossfragshift = val & 0xffff; | 
|  | 2653 | s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff; | 
|  | 2654 | if (s->dma_dac.ossfragshift < 4) | 
|  | 2655 | s->dma_dac.ossfragshift = 4; | 
|  | 2656 | if (s->dma_dac.ossfragshift > 15) | 
|  | 2657 | s->dma_dac.ossfragshift = 15; | 
|  | 2658 | if (s->dma_dac.ossmaxfrags < 4) | 
|  | 2659 | s->dma_dac.ossmaxfrags = 4; | 
|  | 2660 | if (s->status & DO_DUAL_DAC) { | 
|  | 2661 | s->dma_adc.ossfragshift = s->dma_dac.ossfragshift; | 
|  | 2662 | s->dma_adc.ossmaxfrags = s->dma_dac.ossmaxfrags; | 
|  | 2663 | } | 
|  | 2664 | } | 
|  | 2665 | return 0; | 
|  | 2666 |  | 
|  | 2667 | case SNDCTL_DSP_SUBDIVIDE: | 
|  | 2668 | if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || | 
|  | 2669 | (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) | 
|  | 2670 | return -EINVAL; | 
|  | 2671 | if (get_user(val, p)) | 
|  | 2672 | return -EFAULT; | 
|  | 2673 | if (val != 1 && val != 2 && val != 4) | 
|  | 2674 | return -EINVAL; | 
|  | 2675 | if (file->f_mode & FMODE_READ) | 
|  | 2676 | s->dma_adc.subdivision = val; | 
|  | 2677 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2678 | s->dma_dac.subdivision = val; | 
|  | 2679 | if (s->status & DO_DUAL_DAC) | 
|  | 2680 | s->dma_adc.subdivision = val; | 
|  | 2681 | } | 
|  | 2682 | return 0; | 
|  | 2683 |  | 
|  | 2684 | case SOUND_PCM_READ_RATE: | 
|  | 2685 | return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, p); | 
|  | 2686 |  | 
|  | 2687 | case SOUND_PCM_READ_CHANNELS: | 
|  | 2688 | return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, p); | 
|  | 2689 |  | 
|  | 2690 | case SOUND_PCM_READ_BITS: | 
|  | 2691 | return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? 16 : 8, p); | 
|  | 2692 |  | 
|  | 2693 | case SOUND_PCM_READ_FILTER: | 
|  | 2694 | return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, p); | 
|  | 2695 |  | 
|  | 2696 | case SNDCTL_DSP_GETCHANNELMASK: | 
|  | 2697 | return put_user(DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE|DSP_BIND_SPDIF, p); | 
|  | 2698 |  | 
|  | 2699 | case SNDCTL_DSP_BIND_CHANNEL: | 
|  | 2700 | if (get_user(val, p)) | 
|  | 2701 | return -EFAULT; | 
|  | 2702 | if (val == DSP_BIND_QUERY) { | 
|  | 2703 | val = DSP_BIND_FRONT; | 
|  | 2704 | if (s->status & DO_SPDIF_OUT) | 
|  | 2705 | val |= DSP_BIND_SPDIF; | 
|  | 2706 | else { | 
|  | 2707 | if (s->curr_channels == 4) | 
|  | 2708 | val |= DSP_BIND_SURR; | 
|  | 2709 | if (s->curr_channels > 4) | 
|  | 2710 | val |= DSP_BIND_CENTER_LFE; | 
|  | 2711 | } | 
|  | 2712 | } else { | 
|  | 2713 | if (file->f_mode & FMODE_READ) { | 
|  | 2714 | stop_adc(s); | 
|  | 2715 | s->dma_adc.ready = 0; | 
|  | 2716 | if (val & DSP_BIND_SPDIF) { | 
|  | 2717 | set_spdifin(s, s->rateadc); | 
|  | 2718 | if (!(s->status & DO_SPDIF_OUT)) | 
|  | 2719 | val &= ~DSP_BIND_SPDIF; | 
|  | 2720 | } | 
|  | 2721 | } | 
|  | 2722 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2723 | stop_dac(s); | 
|  | 2724 | s->dma_dac.ready = 0; | 
|  | 2725 | if (val & DSP_BIND_SPDIF) { | 
|  | 2726 | set_spdifout(s, s->ratedac); | 
|  | 2727 | set_dac_channels(s, s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1); | 
|  | 2728 | if (!(s->status & DO_SPDIF_OUT)) | 
|  | 2729 | val &= ~DSP_BIND_SPDIF; | 
|  | 2730 | } else { | 
|  | 2731 | int channels; | 
|  | 2732 | int mask; | 
|  | 2733 |  | 
|  | 2734 | mask = val & (DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE); | 
|  | 2735 | switch (mask) { | 
|  | 2736 | case DSP_BIND_FRONT: | 
|  | 2737 | channels = 2; | 
|  | 2738 | break; | 
|  | 2739 | case DSP_BIND_FRONT|DSP_BIND_SURR: | 
|  | 2740 | channels = 4; | 
|  | 2741 | break; | 
|  | 2742 | case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE: | 
|  | 2743 | channels = 6; | 
|  | 2744 | break; | 
|  | 2745 | default: | 
|  | 2746 | channels = s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1; | 
|  | 2747 | break; | 
|  | 2748 | } | 
|  | 2749 | set_dac_channels(s, channels); | 
|  | 2750 | } | 
|  | 2751 | } | 
|  | 2752 | } | 
|  | 2753 | return put_user(val, p); | 
|  | 2754 |  | 
|  | 2755 | case SOUND_PCM_WRITE_FILTER: | 
|  | 2756 | case SNDCTL_DSP_MAPINBUF: | 
|  | 2757 | case SNDCTL_DSP_MAPOUTBUF: | 
|  | 2758 | case SNDCTL_DSP_SETSYNCRO: | 
|  | 2759 | return -EINVAL; | 
|  | 2760 | case SNDCTL_SPDIF_COPYRIGHT: | 
|  | 2761 | if (get_user(val, p)) | 
|  | 2762 | return -EFAULT; | 
|  | 2763 | set_spdif_copyright(s, val); | 
|  | 2764 | return 0; | 
|  | 2765 | case SNDCTL_SPDIF_LOOP: | 
|  | 2766 | if (get_user(val, p)) | 
|  | 2767 | return -EFAULT; | 
|  | 2768 | set_spdif_loop(s, val); | 
|  | 2769 | return 0; | 
|  | 2770 | case SNDCTL_SPDIF_MONITOR: | 
|  | 2771 | if (get_user(val, p)) | 
|  | 2772 | return -EFAULT; | 
|  | 2773 | set_spdif_monitor(s, val); | 
|  | 2774 | return 0; | 
|  | 2775 | case SNDCTL_SPDIF_LEVEL: | 
|  | 2776 | if (get_user(val, p)) | 
|  | 2777 | return -EFAULT; | 
|  | 2778 | set_spdifout_level(s, val); | 
|  | 2779 | return 0; | 
|  | 2780 | case SNDCTL_SPDIF_INV: | 
|  | 2781 | if (get_user(val, p)) | 
|  | 2782 | return -EFAULT; | 
|  | 2783 | set_spdifin_inverse(s, val); | 
|  | 2784 | return 0; | 
|  | 2785 | case SNDCTL_SPDIF_SEL2: | 
|  | 2786 | if (get_user(val, p)) | 
|  | 2787 | return -EFAULT; | 
|  | 2788 | set_spdifin_channel2(s, val); | 
|  | 2789 | return 0; | 
|  | 2790 | case SNDCTL_SPDIF_VALID: | 
|  | 2791 | if (get_user(val, p)) | 
|  | 2792 | return -EFAULT; | 
|  | 2793 | set_spdifin_valid(s, val); | 
|  | 2794 | return 0; | 
|  | 2795 | case SNDCTL_SPDIFOUT: | 
|  | 2796 | if (get_user(val, p)) | 
|  | 2797 | return -EFAULT; | 
|  | 2798 | set_spdifout(s, val ? s->ratedac : 0); | 
|  | 2799 | return 0; | 
|  | 2800 | case SNDCTL_SPDIFIN: | 
|  | 2801 | if (get_user(val, p)) | 
|  | 2802 | return -EFAULT; | 
|  | 2803 | set_spdifin(s, val ? s->rateadc : 0); | 
|  | 2804 | return 0; | 
|  | 2805 | } | 
|  | 2806 | return mixer_ioctl(s, cmd, arg); | 
|  | 2807 | } | 
|  | 2808 |  | 
|  | 2809 | static int cm_open(struct inode *inode, struct file *file) | 
|  | 2810 | { | 
|  | 2811 | int minor = iminor(inode); | 
|  | 2812 | DECLARE_WAITQUEUE(wait, current); | 
|  | 2813 | unsigned char fmtm = ~0, fmts = 0; | 
|  | 2814 | struct list_head *list; | 
|  | 2815 | struct cm_state *s; | 
|  | 2816 |  | 
|  | 2817 | for (list = devs.next; ; list = list->next) { | 
|  | 2818 | if (list == &devs) | 
|  | 2819 | return -ENODEV; | 
|  | 2820 | s = list_entry(list, struct cm_state, devs); | 
|  | 2821 | if (!((s->dev_audio ^ minor) & ~0xf)) | 
|  | 2822 | break; | 
|  | 2823 | } | 
|  | 2824 | VALIDATE_STATE(s); | 
|  | 2825 | file->private_data = s; | 
|  | 2826 | /* wait for device to become free */ | 
|  | 2827 | down(&s->open_sem); | 
|  | 2828 | while (s->open_mode & file->f_mode) { | 
|  | 2829 | if (file->f_flags & O_NONBLOCK) { | 
|  | 2830 | up(&s->open_sem); | 
|  | 2831 | return -EBUSY; | 
|  | 2832 | } | 
|  | 2833 | add_wait_queue(&s->open_wait, &wait); | 
|  | 2834 | __set_current_state(TASK_INTERRUPTIBLE); | 
|  | 2835 | up(&s->open_sem); | 
|  | 2836 | schedule(); | 
|  | 2837 | remove_wait_queue(&s->open_wait, &wait); | 
|  | 2838 | set_current_state(TASK_RUNNING); | 
|  | 2839 | if (signal_pending(current)) | 
|  | 2840 | return -ERESTARTSYS; | 
|  | 2841 | down(&s->open_sem); | 
|  | 2842 | } | 
|  | 2843 | if (file->f_mode & FMODE_READ) { | 
|  | 2844 | s->status &= ~DO_BIGENDIAN_R; | 
|  | 2845 | fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT); | 
|  | 2846 | if ((minor & 0xf) == SND_DEV_DSP16) | 
|  | 2847 | fmts |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT; | 
|  | 2848 | s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; | 
|  | 2849 | s->dma_adc.enabled = 1; | 
|  | 2850 | set_adc_rate(s, 8000); | 
|  | 2851 | // spdif-in is turnned off by default | 
|  | 2852 | set_spdifin(s, 0); | 
|  | 2853 | } | 
|  | 2854 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2855 | s->status &= ~DO_BIGENDIAN_W; | 
|  | 2856 | fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT); | 
|  | 2857 | if ((minor & 0xf) == SND_DEV_DSP16) | 
|  | 2858 | fmts |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; | 
|  | 2859 | s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; | 
|  | 2860 | s->dma_dac.enabled = 1; | 
|  | 2861 | set_dac_rate(s, 8000); | 
|  | 2862 | // clear previous multichannel, spdif, ac3 state | 
|  | 2863 | set_spdifout(s, 0); | 
|  | 2864 | set_ac3(s, 0); | 
|  | 2865 | set_dac_channels(s, 1); | 
|  | 2866 | } | 
|  | 2867 | set_fmt(s, fmtm, fmts); | 
|  | 2868 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | 
|  | 2869 | up(&s->open_sem); | 
|  | 2870 | return nonseekable_open(inode, file); | 
|  | 2871 | } | 
|  | 2872 |  | 
|  | 2873 | static int cm_release(struct inode *inode, struct file *file) | 
|  | 2874 | { | 
|  | 2875 | struct cm_state *s = (struct cm_state *)file->private_data; | 
|  | 2876 |  | 
|  | 2877 | VALIDATE_STATE(s); | 
|  | 2878 | lock_kernel(); | 
|  | 2879 | if (file->f_mode & FMODE_WRITE) | 
|  | 2880 | drain_dac(s, file->f_flags & O_NONBLOCK); | 
|  | 2881 | down(&s->open_sem); | 
|  | 2882 | if (file->f_mode & FMODE_WRITE) { | 
|  | 2883 | stop_dac(s); | 
|  | 2884 |  | 
|  | 2885 | dealloc_dmabuf(s, &s->dma_dac); | 
|  | 2886 | if (s->status & DO_DUAL_DAC) | 
|  | 2887 | dealloc_dmabuf(s, &s->dma_adc); | 
|  | 2888 |  | 
|  | 2889 | if (s->status & DO_MULTI_CH) | 
|  | 2890 | set_dac_channels(s, 1); | 
|  | 2891 | if (s->status & DO_AC3) | 
|  | 2892 | set_ac3(s, 0); | 
|  | 2893 | if (s->status & DO_SPDIF_OUT) | 
|  | 2894 | set_spdifout(s, 0); | 
|  | 2895 | /* enable SPDIF loop */ | 
|  | 2896 | set_spdif_loop(s, spdif_loop); | 
|  | 2897 | s->status &= ~DO_BIGENDIAN_W; | 
|  | 2898 | } | 
|  | 2899 | if (file->f_mode & FMODE_READ) { | 
|  | 2900 | stop_adc(s); | 
|  | 2901 | dealloc_dmabuf(s, &s->dma_adc); | 
|  | 2902 | s->status &= ~DO_BIGENDIAN_R; | 
|  | 2903 | } | 
|  | 2904 | s->open_mode &= ~(file->f_mode & (FMODE_READ|FMODE_WRITE)); | 
|  | 2905 | up(&s->open_sem); | 
|  | 2906 | wake_up(&s->open_wait); | 
|  | 2907 | unlock_kernel(); | 
|  | 2908 | return 0; | 
|  | 2909 | } | 
|  | 2910 |  | 
|  | 2911 | static /*const*/ struct file_operations cm_audio_fops = { | 
|  | 2912 | .owner	 = THIS_MODULE, | 
|  | 2913 | .llseek	 = no_llseek, | 
|  | 2914 | .read	 = cm_read, | 
|  | 2915 | .write	 = cm_write, | 
|  | 2916 | .poll	 = cm_poll, | 
|  | 2917 | .ioctl	 = cm_ioctl, | 
|  | 2918 | .mmap	 = cm_mmap, | 
|  | 2919 | .open	 = cm_open, | 
|  | 2920 | .release = cm_release, | 
|  | 2921 | }; | 
|  | 2922 |  | 
|  | 2923 | /* --------------------------------------------------------------------- */ | 
|  | 2924 |  | 
|  | 2925 | static struct initvol { | 
|  | 2926 | int mixch; | 
|  | 2927 | int vol; | 
|  | 2928 | } initvol[] __devinitdata = { | 
|  | 2929 | { SOUND_MIXER_WRITE_CD, 0x4f4f }, | 
|  | 2930 | { SOUND_MIXER_WRITE_LINE, 0x4f4f }, | 
|  | 2931 | { SOUND_MIXER_WRITE_MIC, 0x4f4f }, | 
|  | 2932 | { SOUND_MIXER_WRITE_SYNTH, 0x4f4f }, | 
|  | 2933 | { SOUND_MIXER_WRITE_VOLUME, 0x4f4f }, | 
|  | 2934 | { SOUND_MIXER_WRITE_PCM, 0x4f4f } | 
|  | 2935 | }; | 
|  | 2936 |  | 
|  | 2937 | /* check chip version and capability */ | 
|  | 2938 | static int query_chip(struct cm_state *s) | 
|  | 2939 | { | 
|  | 2940 | int ChipVersion = -1; | 
|  | 2941 | unsigned char RegValue; | 
|  | 2942 |  | 
|  | 2943 | // check reg 0Ch, bit 24-31 | 
|  | 2944 | RegValue = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 3); | 
|  | 2945 | if (RegValue == 0) { | 
|  | 2946 | // check reg 08h, bit 24-28 | 
|  | 2947 | RegValue = inb(s->iobase + CODEC_CMI_CHFORMAT + 3); | 
|  | 2948 | RegValue &= 0x1f; | 
|  | 2949 | if (RegValue == 0) { | 
|  | 2950 | ChipVersion = 33; | 
|  | 2951 | s->max_channels = 4; | 
|  | 2952 | s->capability |= CAN_AC3_SW; | 
|  | 2953 | s->capability |= CAN_DUAL_DAC; | 
|  | 2954 | } else { | 
|  | 2955 | ChipVersion = 37; | 
|  | 2956 | s->max_channels = 4; | 
|  | 2957 | s->capability |= CAN_AC3_HW; | 
|  | 2958 | s->capability |= CAN_DUAL_DAC; | 
|  | 2959 | } | 
|  | 2960 | } else { | 
|  | 2961 | // check reg 0Ch, bit 26 | 
|  | 2962 | if (RegValue & (1 << (26-24))) { | 
|  | 2963 | ChipVersion = 39; | 
|  | 2964 | if (RegValue & (1 << (24-24))) | 
|  | 2965 | s->max_channels = 6; | 
|  | 2966 | else | 
|  | 2967 | s->max_channels = 4; | 
|  | 2968 | s->capability |= CAN_AC3_HW; | 
|  | 2969 | s->capability |= CAN_DUAL_DAC; | 
|  | 2970 | s->capability |= CAN_MULTI_CH_HW; | 
|  | 2971 | s->capability |= CAN_LINE_AS_BASS; | 
|  | 2972 | s->capability |= CAN_MIC_AS_BASS; | 
|  | 2973 | } else { | 
|  | 2974 | ChipVersion = 55; // 4 or 6 channels | 
|  | 2975 | s->max_channels = 6; | 
|  | 2976 | s->capability |= CAN_AC3_HW; | 
|  | 2977 | s->capability |= CAN_DUAL_DAC; | 
|  | 2978 | s->capability |= CAN_MULTI_CH_HW; | 
|  | 2979 | s->capability |= CAN_LINE_AS_BASS; | 
|  | 2980 | s->capability |= CAN_MIC_AS_BASS; | 
|  | 2981 | } | 
|  | 2982 | } | 
|  | 2983 | s->capability |= CAN_LINE_AS_REAR; | 
|  | 2984 | return ChipVersion; | 
|  | 2985 | } | 
|  | 2986 |  | 
|  | 2987 | #ifdef CONFIG_SOUND_CMPCI_JOYSTICK | 
|  | 2988 | static int __devinit cm_create_gameport(struct cm_state *s, int io_port) | 
|  | 2989 | { | 
|  | 2990 | struct gameport *gp; | 
|  | 2991 |  | 
|  | 2992 | if (!request_region(io_port, CM_EXTENT_GAME, "cmpci GAME")) { | 
|  | 2993 | printk(KERN_ERR "cmpci: gameport io ports 0x%#x in use\n", io_port); | 
|  | 2994 | return -EBUSY; | 
|  | 2995 | } | 
|  | 2996 |  | 
|  | 2997 | if (!(s->gameport = gp = gameport_allocate_port())) { | 
|  | 2998 | printk(KERN_ERR "cmpci: can not allocate memory for gameport\n"); | 
|  | 2999 | release_region(io_port, CM_EXTENT_GAME); | 
|  | 3000 | return -ENOMEM; | 
|  | 3001 | } | 
|  | 3002 |  | 
|  | 3003 | gameport_set_name(gp, "C-Media GP"); | 
|  | 3004 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); | 
|  | 3005 | gp->dev.parent = &s->dev->dev; | 
|  | 3006 | gp->io = io_port; | 
|  | 3007 |  | 
|  | 3008 | /* enable joystick */ | 
|  | 3009 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02); | 
|  | 3010 |  | 
|  | 3011 | gameport_register_port(gp); | 
|  | 3012 |  | 
|  | 3013 | return 0; | 
|  | 3014 | } | 
|  | 3015 |  | 
|  | 3016 | static void __devexit cm_free_gameport(struct cm_state *s) | 
|  | 3017 | { | 
|  | 3018 | if (s->gameport) { | 
|  | 3019 | int gpio = s->gameport->io; | 
|  | 3020 |  | 
|  | 3021 | gameport_unregister_port(s->gameport); | 
|  | 3022 | s->gameport = NULL; | 
|  | 3023 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); | 
|  | 3024 | release_region(gpio, CM_EXTENT_GAME); | 
|  | 3025 | } | 
|  | 3026 | } | 
|  | 3027 | #else | 
|  | 3028 | static inline int cm_create_gameport(struct cm_state *s, int io_port) { return -ENOSYS; } | 
|  | 3029 | static inline void cm_free_gameport(struct cm_state *s) { } | 
|  | 3030 | #endif | 
|  | 3031 |  | 
|  | 3032 | #define	echo_option(x)\ | 
|  | 3033 | if (x) strcat(options, "" #x " ") | 
|  | 3034 |  | 
|  | 3035 | static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 
|  | 3036 | { | 
|  | 3037 | struct cm_state *s; | 
|  | 3038 | mm_segment_t fs; | 
|  | 3039 | int i, val, ret; | 
|  | 3040 | unsigned char reg_mask; | 
|  | 3041 | int timeout; | 
|  | 3042 | struct resource *ports; | 
|  | 3043 | struct { | 
|  | 3044 | unsigned short	deviceid; | 
|  | 3045 | char		*devicename; | 
|  | 3046 | } devicetable[] = { | 
|  | 3047 | { PCI_DEVICE_ID_CMEDIA_CM8338A, "CM8338A" }, | 
|  | 3048 | { PCI_DEVICE_ID_CMEDIA_CM8338B, "CM8338B" }, | 
|  | 3049 | { PCI_DEVICE_ID_CMEDIA_CM8738,  "CM8738" }, | 
|  | 3050 | { PCI_DEVICE_ID_CMEDIA_CM8738B, "CM8738B" }, | 
|  | 3051 | }; | 
|  | 3052 | char	*devicename = "unknown"; | 
|  | 3053 | char	options[256]; | 
|  | 3054 |  | 
|  | 3055 | if ((ret = pci_enable_device(pcidev))) | 
|  | 3056 | return ret; | 
|  | 3057 | if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO)) | 
|  | 3058 | return -ENODEV; | 
|  | 3059 | if (pcidev->irq == 0) | 
|  | 3060 | return -ENODEV; | 
|  | 3061 | i = pci_set_dma_mask(pcidev, 0xffffffff); | 
|  | 3062 | if (i) { | 
|  | 3063 | printk(KERN_WARNING "cmpci: architecture does not support 32bit PCI busmaster DMA\n"); | 
|  | 3064 | return i; | 
|  | 3065 | } | 
|  | 3066 | s = kmalloc(sizeof(*s), GFP_KERNEL); | 
|  | 3067 | if (!s) { | 
|  | 3068 | printk(KERN_WARNING "cmpci: out of memory\n"); | 
|  | 3069 | return -ENOMEM; | 
|  | 3070 | } | 
|  | 3071 | /* search device name */ | 
|  | 3072 | for (i = 0; i < sizeof(devicetable) / sizeof(devicetable[0]); i++) { | 
|  | 3073 | if (devicetable[i].deviceid == pcidev->device) { | 
|  | 3074 | devicename = devicetable[i].devicename; | 
|  | 3075 | break; | 
|  | 3076 | } | 
|  | 3077 | } | 
|  | 3078 | memset(s, 0, sizeof(struct cm_state)); | 
|  | 3079 | init_waitqueue_head(&s->dma_adc.wait); | 
|  | 3080 | init_waitqueue_head(&s->dma_dac.wait); | 
|  | 3081 | init_waitqueue_head(&s->open_wait); | 
|  | 3082 | init_MUTEX(&s->open_sem); | 
|  | 3083 | spin_lock_init(&s->lock); | 
|  | 3084 | s->magic = CM_MAGIC; | 
|  | 3085 | s->dev = pcidev; | 
|  | 3086 | s->iobase = pci_resource_start(pcidev, 0); | 
|  | 3087 | s->iosynth = fmio; | 
|  | 3088 | s->iomidi = mpuio; | 
|  | 3089 | #ifdef CONFIG_SOUND_CMPCI_MIDI | 
|  | 3090 | s->midi_devc = 0; | 
|  | 3091 | #endif | 
|  | 3092 | s->status = 0; | 
|  | 3093 | if (s->iobase == 0) | 
|  | 3094 | return -ENODEV; | 
|  | 3095 | s->irq = pcidev->irq; | 
|  | 3096 |  | 
|  | 3097 | if (!request_region(s->iobase, CM_EXTENT_CODEC, "cmpci")) { | 
|  | 3098 | printk(KERN_ERR "cmpci: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1); | 
|  | 3099 | ret = -EBUSY; | 
|  | 3100 | goto err_region5; | 
|  | 3101 | } | 
|  | 3102 | /* dump parameters */ | 
|  | 3103 | strcpy(options, "cmpci: "); | 
|  | 3104 | echo_option(joystick); | 
|  | 3105 | echo_option(spdif_inverse); | 
|  | 3106 | echo_option(spdif_loop); | 
|  | 3107 | echo_option(spdif_out); | 
|  | 3108 | echo_option(use_line_as_rear); | 
|  | 3109 | echo_option(use_line_as_bass); | 
|  | 3110 | echo_option(use_mic_as_bass); | 
|  | 3111 | echo_option(mic_boost); | 
|  | 3112 | echo_option(hw_copy); | 
|  | 3113 | printk(KERN_INFO "%s\n", options); | 
|  | 3114 |  | 
|  | 3115 | /* initialize codec registers */ | 
|  | 3116 | outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2);  /* disable ints */ | 
|  | 3117 | outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */ | 
|  | 3118 | /* reset mixer */ | 
|  | 3119 | wrmixer(s, DSP_MIX_DATARESETIDX, 0); | 
|  | 3120 |  | 
|  | 3121 | /* request irq */ | 
|  | 3122 | if ((ret = request_irq(s->irq, cm_interrupt, SA_SHIRQ, "cmpci", s))) { | 
|  | 3123 | printk(KERN_ERR "cmpci: irq %u in use\n", s->irq); | 
|  | 3124 | goto err_irq; | 
|  | 3125 | } | 
|  | 3126 | printk(KERN_INFO "cmpci: found %s adapter at io %#x irq %u\n", | 
|  | 3127 | devicename, s->iobase, s->irq); | 
|  | 3128 | /* register devices */ | 
|  | 3129 | if ((s->dev_audio = register_sound_dsp(&cm_audio_fops, -1)) < 0) { | 
|  | 3130 | ret = s->dev_audio; | 
|  | 3131 | goto err_dev1; | 
|  | 3132 | } | 
|  | 3133 | if ((s->dev_mixer = register_sound_mixer(&cm_mixer_fops, -1)) < 0) { | 
|  | 3134 | ret = s->dev_mixer; | 
|  | 3135 | goto err_dev2; | 
|  | 3136 | } | 
|  | 3137 | pci_set_master(pcidev);	/* enable bus mastering */ | 
|  | 3138 | /* initialize the chips */ | 
|  | 3139 | fs = get_fs(); | 
|  | 3140 | set_fs(KERNEL_DS); | 
|  | 3141 | /* set mixer output */ | 
|  | 3142 | frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, 0x1f); | 
|  | 3143 | /* set mixer input */ | 
|  | 3144 | val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD|SOUND_MASK_MIC; | 
|  | 3145 | mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); | 
|  | 3146 | for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { | 
|  | 3147 | val = initvol[i].vol; | 
|  | 3148 | mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val); | 
|  | 3149 | } | 
|  | 3150 | set_fs(fs); | 
|  | 3151 | /* use channel 1 for playback, channel 0 for record */ | 
|  | 3152 | maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~CHADC1, CHADC0); | 
|  | 3153 | /* turn off VMIC3 - mic boost */ | 
|  | 3154 | if (mic_boost) | 
|  | 3155 | maskb(s->iobase + CODEC_CMI_MIXER2, ~1, 0); | 
|  | 3156 | else | 
|  | 3157 | maskb(s->iobase + CODEC_CMI_MIXER2, ~0, 1); | 
|  | 3158 | s->deviceid = pcidev->device; | 
|  | 3159 |  | 
|  | 3160 | if (pcidev->device == PCI_DEVICE_ID_CMEDIA_CM8738 | 
|  | 3161 | || pcidev->device == PCI_DEVICE_ID_CMEDIA_CM8738B) { | 
|  | 3162 |  | 
|  | 3163 | /* chip version and hw capability check */ | 
|  | 3164 | s->chip_version = query_chip(s); | 
|  | 3165 | printk(KERN_INFO "cmpci: chip version = 0%d\n", s->chip_version); | 
|  | 3166 |  | 
|  | 3167 | /* set SPDIF-in inverse before enable SPDIF loop */ | 
|  | 3168 | set_spdifin_inverse(s, spdif_inverse); | 
|  | 3169 |  | 
|  | 3170 | /* use SPDIF in #1 */ | 
|  | 3171 | set_spdifin_channel2(s, 0); | 
|  | 3172 | } else { | 
|  | 3173 | s->chip_version = 0; | 
|  | 3174 | /* 8338 will fall here */ | 
|  | 3175 | s->max_channels = 4; | 
|  | 3176 | s->capability |= CAN_DUAL_DAC; | 
|  | 3177 | s->capability |= CAN_LINE_AS_REAR; | 
|  | 3178 | } | 
|  | 3179 | /* enable SPDIF loop */ | 
|  | 3180 | set_spdif_loop(s, spdif_loop); | 
|  | 3181 |  | 
|  | 3182 | // enable 4 speaker mode (analog duplicate) | 
|  | 3183 | set_hw_copy(s, hw_copy); | 
|  | 3184 |  | 
|  | 3185 | reg_mask = 0; | 
|  | 3186 | #ifdef CONFIG_SOUND_CMPCI_FM | 
|  | 3187 | /* disable FM */ | 
|  | 3188 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~8, 0); | 
|  | 3189 | if (s->iosynth) { | 
|  | 3190 | /* don't enable OPL3 if there is one */ | 
|  | 3191 | if (opl3_detect(s->iosynth, NULL)) { | 
|  | 3192 | s->iosynth = 0; | 
|  | 3193 | } else { | 
|  | 3194 | /* set IO based at 0x388 */ | 
|  | 3195 | switch (s->iosynth) { | 
|  | 3196 | case 0x388: | 
|  | 3197 | reg_mask = 0; | 
|  | 3198 | break; | 
|  | 3199 | case 0x3C8: | 
|  | 3200 | reg_mask = 0x01; | 
|  | 3201 | break; | 
|  | 3202 | case 0x3E0: | 
|  | 3203 | reg_mask = 0x02; | 
|  | 3204 | break; | 
|  | 3205 | case 0x3E8: | 
|  | 3206 | reg_mask = 0x03; | 
|  | 3207 | break; | 
|  | 3208 | default: | 
|  | 3209 | s->iosynth = 0; | 
|  | 3210 | break; | 
|  | 3211 | } | 
|  | 3212 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x03, reg_mask); | 
|  | 3213 | /* enable FM */ | 
|  | 3214 | if (s->iosynth) { | 
|  | 3215 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 8); | 
|  | 3216 | if (opl3_detect(s->iosynth, NULL)) | 
|  | 3217 | ret = opl3_init(s->iosynth, NULL, THIS_MODULE); | 
|  | 3218 | else { | 
|  | 3219 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~8, 0); | 
|  | 3220 | s->iosynth = 0; | 
|  | 3221 | } | 
|  | 3222 | } | 
|  | 3223 | } | 
|  | 3224 | } | 
|  | 3225 | #endif | 
|  | 3226 | #ifdef CONFIG_SOUND_CMPCI_MIDI | 
|  | 3227 | switch (s->iomidi) { | 
|  | 3228 | case 0x330: | 
|  | 3229 | reg_mask = 0; | 
|  | 3230 | break; | 
|  | 3231 | case 0x320: | 
|  | 3232 | reg_mask = 0x20; | 
|  | 3233 | break; | 
|  | 3234 | case 0x310: | 
|  | 3235 | reg_mask = 0x40; | 
|  | 3236 | break; | 
|  | 3237 | case 0x300: | 
|  | 3238 | reg_mask = 0x60; | 
|  | 3239 | break; | 
|  | 3240 | default: | 
|  | 3241 | s->iomidi = 0; | 
|  | 3242 | goto skip_mpu; | 
|  | 3243 | } | 
|  | 3244 | ports = request_region(s->iomidi, 2, "mpu401"); | 
|  | 3245 | if (!ports) | 
|  | 3246 | goto skip_mpu; | 
|  | 3247 | /* disable MPU-401 */ | 
|  | 3248 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0); | 
|  | 3249 | s->mpu_data.name = "cmpci mpu"; | 
|  | 3250 | s->mpu_data.io_base = s->iomidi; | 
|  | 3251 | s->mpu_data.irq = -s->irq;	// tell mpu401 to share irq | 
|  | 3252 | if (probe_mpu401(&s->mpu_data, ports)) { | 
|  | 3253 | release_region(s->iomidi, 2); | 
|  | 3254 | s->iomidi = 0; | 
|  | 3255 | goto skip_mpu; | 
|  | 3256 | } | 
|  | 3257 | maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask); | 
|  | 3258 | /* enable MPU-401 */ | 
|  | 3259 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04); | 
|  | 3260 | /* clear all previously received interrupt */ | 
|  | 3261 | for (timeout = 900000; timeout > 0; timeout--) { | 
|  | 3262 | if ((inb(s->iomidi + 1) && 0x80) == 0) | 
|  | 3263 | inb(s->iomidi); | 
|  | 3264 | else | 
|  | 3265 | break; | 
|  | 3266 | } | 
|  | 3267 | if (!probe_mpu401(&s->mpu_data, ports)) { | 
|  | 3268 | release_region(s->iomidi, 2); | 
|  | 3269 | s->iomidi = 0; | 
|  | 3270 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04); | 
|  | 3271 | } else { | 
|  | 3272 | attach_mpu401(&s->mpu_data, THIS_MODULE); | 
|  | 3273 | s->midi_devc = s->mpu_data.slots[1]; | 
|  | 3274 | } | 
|  | 3275 | skip_mpu: | 
|  | 3276 | #endif | 
|  | 3277 | /* disable joystick port */ | 
|  | 3278 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); | 
|  | 3279 | if (joystick) | 
|  | 3280 | cm_create_gameport(s, 0x200); | 
|  | 3281 |  | 
|  | 3282 | /* store it in the driver field */ | 
|  | 3283 | pci_set_drvdata(pcidev, s); | 
|  | 3284 | /* put it into driver list */ | 
|  | 3285 | list_add_tail(&s->devs, &devs); | 
|  | 3286 | /* increment devindex */ | 
|  | 3287 | if (devindex < NR_DEVICE-1) | 
|  | 3288 | devindex++; | 
|  | 3289 | return 0; | 
|  | 3290 |  | 
|  | 3291 | err_dev2: | 
|  | 3292 | unregister_sound_dsp(s->dev_audio); | 
|  | 3293 | err_dev1: | 
|  | 3294 | printk(KERN_ERR "cmpci: cannot register misc device\n"); | 
|  | 3295 | free_irq(s->irq, s); | 
|  | 3296 | err_irq: | 
|  | 3297 | release_region(s->iobase, CM_EXTENT_CODEC); | 
|  | 3298 | err_region5: | 
|  | 3299 | kfree(s); | 
|  | 3300 | return ret; | 
|  | 3301 | } | 
|  | 3302 |  | 
|  | 3303 | /* --------------------------------------------------------------------- */ | 
|  | 3304 |  | 
|  | 3305 | MODULE_AUTHOR("ChenLi Tien, cltien@cmedia.com.tw"); | 
|  | 3306 | MODULE_DESCRIPTION("CM8x38 Audio Driver"); | 
|  | 3307 | MODULE_LICENSE("GPL"); | 
|  | 3308 |  | 
|  | 3309 | static void __devexit cm_remove(struct pci_dev *dev) | 
|  | 3310 | { | 
|  | 3311 | struct cm_state *s = pci_get_drvdata(dev); | 
|  | 3312 |  | 
|  | 3313 | if (!s) | 
|  | 3314 | return; | 
|  | 3315 |  | 
|  | 3316 | cm_free_gameport(s); | 
|  | 3317 |  | 
|  | 3318 | #ifdef CONFIG_SOUND_CMPCI_FM | 
|  | 3319 | if (s->iosynth) { | 
|  | 3320 | /* disable FM */ | 
|  | 3321 | maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~8, 0); | 
|  | 3322 | } | 
|  | 3323 | #endif | 
|  | 3324 | #ifdef CONFIG_SOUND_CMPCI_MIDI | 
|  | 3325 | if (s->iomidi) { | 
|  | 3326 | unload_mpu401(&s->mpu_data); | 
|  | 3327 | /* disable MPU-401 */ | 
|  | 3328 | maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0); | 
|  | 3329 | } | 
|  | 3330 | #endif | 
|  | 3331 | set_spdif_loop(s, 0); | 
|  | 3332 | list_del(&s->devs); | 
|  | 3333 | outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2);  /* disable ints */ | 
|  | 3334 | synchronize_irq(s->irq); | 
|  | 3335 | outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */ | 
|  | 3336 | free_irq(s->irq, s); | 
|  | 3337 |  | 
|  | 3338 | /* reset mixer */ | 
|  | 3339 | wrmixer(s, DSP_MIX_DATARESETIDX, 0); | 
|  | 3340 |  | 
|  | 3341 | release_region(s->iobase, CM_EXTENT_CODEC); | 
|  | 3342 | unregister_sound_dsp(s->dev_audio); | 
|  | 3343 | unregister_sound_mixer(s->dev_mixer); | 
|  | 3344 | kfree(s); | 
|  | 3345 | pci_set_drvdata(dev, NULL); | 
|  | 3346 | } | 
|  | 3347 |  | 
|  | 3348 | static struct pci_device_id id_table[] __devinitdata = { | 
|  | 3349 | { PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, | 
|  | 3350 | { PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, | 
|  | 3351 | { PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, | 
|  | 3352 | { PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, | 
|  | 3353 | { 0, } | 
|  | 3354 | }; | 
|  | 3355 |  | 
|  | 3356 | MODULE_DEVICE_TABLE(pci, id_table); | 
|  | 3357 |  | 
|  | 3358 | static struct pci_driver cm_driver = { | 
|  | 3359 | .name	 = "cmpci", | 
|  | 3360 | .id_table = id_table, | 
|  | 3361 | .probe	 = cm_probe, | 
|  | 3362 | .remove	 = __devexit_p(cm_remove) | 
|  | 3363 | }; | 
|  | 3364 |  | 
|  | 3365 | static int __init init_cmpci(void) | 
|  | 3366 | { | 
|  | 3367 | printk(KERN_INFO "cmpci: version $Revision: 6.82 $ time " __TIME__ " " __DATE__ "\n"); | 
|  | 3368 | return pci_module_init(&cm_driver); | 
|  | 3369 | } | 
|  | 3370 |  | 
|  | 3371 | static void __exit cleanup_cmpci(void) | 
|  | 3372 | { | 
|  | 3373 | printk(KERN_INFO "cmpci: unloading\n"); | 
|  | 3374 | pci_unregister_driver(&cm_driver); | 
|  | 3375 | } | 
|  | 3376 |  | 
|  | 3377 | module_init(init_cmpci); | 
|  | 3378 | module_exit(cleanup_cmpci); |