0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/time.h>
0015 #include <sound/core.h>
0016 #include <sound/emu10k1.h>
0017 #include <linux/delay.h>
0018 #include <linux/export.h>
0019 #include "p17v.h"
0020
0021 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
0022 {
0023 unsigned long flags;
0024 unsigned int regptr, val;
0025 unsigned int mask;
0026
0027 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
0028 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
0029
0030 if (reg & 0xff000000) {
0031 unsigned char size, offset;
0032
0033 size = (reg >> 24) & 0x3f;
0034 offset = (reg >> 16) & 0x1f;
0035 mask = ((1 << size) - 1) << offset;
0036
0037 spin_lock_irqsave(&emu->emu_lock, flags);
0038 outl(regptr, emu->port + PTR);
0039 val = inl(emu->port + DATA);
0040 spin_unlock_irqrestore(&emu->emu_lock, flags);
0041
0042 return (val & mask) >> offset;
0043 } else {
0044 spin_lock_irqsave(&emu->emu_lock, flags);
0045 outl(regptr, emu->port + PTR);
0046 val = inl(emu->port + DATA);
0047 spin_unlock_irqrestore(&emu->emu_lock, flags);
0048 return val;
0049 }
0050 }
0051
0052 EXPORT_SYMBOL(snd_emu10k1_ptr_read);
0053
0054 void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
0055 {
0056 unsigned int regptr;
0057 unsigned long flags;
0058 unsigned int mask;
0059
0060 if (snd_BUG_ON(!emu))
0061 return;
0062 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
0063 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
0064
0065 if (reg & 0xff000000) {
0066 unsigned char size, offset;
0067
0068 size = (reg >> 24) & 0x3f;
0069 offset = (reg >> 16) & 0x1f;
0070 mask = ((1 << size) - 1) << offset;
0071 data = (data << offset) & mask;
0072
0073 spin_lock_irqsave(&emu->emu_lock, flags);
0074 outl(regptr, emu->port + PTR);
0075 data |= inl(emu->port + DATA) & ~mask;
0076 outl(data, emu->port + DATA);
0077 spin_unlock_irqrestore(&emu->emu_lock, flags);
0078 } else {
0079 spin_lock_irqsave(&emu->emu_lock, flags);
0080 outl(regptr, emu->port + PTR);
0081 outl(data, emu->port + DATA);
0082 spin_unlock_irqrestore(&emu->emu_lock, flags);
0083 }
0084 }
0085
0086 EXPORT_SYMBOL(snd_emu10k1_ptr_write);
0087
0088 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu,
0089 unsigned int reg,
0090 unsigned int chn)
0091 {
0092 unsigned long flags;
0093 unsigned int regptr, val;
0094
0095 regptr = (reg << 16) | chn;
0096
0097 spin_lock_irqsave(&emu->emu_lock, flags);
0098 outl(regptr, emu->port + 0x20 + PTR);
0099 val = inl(emu->port + 0x20 + DATA);
0100 spin_unlock_irqrestore(&emu->emu_lock, flags);
0101 return val;
0102 }
0103
0104 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu,
0105 unsigned int reg,
0106 unsigned int chn,
0107 unsigned int data)
0108 {
0109 unsigned int regptr;
0110 unsigned long flags;
0111
0112 regptr = (reg << 16) | chn;
0113
0114 spin_lock_irqsave(&emu->emu_lock, flags);
0115 outl(regptr, emu->port + 0x20 + PTR);
0116 outl(data, emu->port + 0x20 + DATA);
0117 spin_unlock_irqrestore(&emu->emu_lock, flags);
0118 }
0119
0120 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
0121 unsigned int data)
0122 {
0123 unsigned int reset, set;
0124 unsigned int reg, tmp;
0125 int n, result;
0126 int err = 0;
0127
0128
0129 spin_lock(&emu->spi_lock);
0130 if (emu->card_capabilities->ca0108_chip)
0131 reg = 0x3c;
0132 else {
0133
0134
0135 err = 1;
0136 goto spi_write_exit;
0137 }
0138 if (data > 0xffff) {
0139
0140 err = 1;
0141 goto spi_write_exit;
0142 }
0143
0144 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
0145 reset = (tmp & ~0x3ffff) | 0x20000;
0146 set = reset | 0x10000;
0147 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
0148 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
0149 snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
0150 result = 1;
0151
0152 for (n = 0; n < 100; n++) {
0153 udelay(10);
0154 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
0155 if (!(tmp & 0x10000)) {
0156 result = 0;
0157 break;
0158 }
0159 }
0160 if (result) {
0161
0162 err = 1;
0163 goto spi_write_exit;
0164 }
0165 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
0166 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
0167 err = 0;
0168 spi_write_exit:
0169 spin_unlock(&emu->spi_lock);
0170 return err;
0171 }
0172
0173
0174 int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
0175 u32 reg,
0176 u32 value)
0177 {
0178 u32 tmp;
0179 int timeout = 0;
0180 int status;
0181 int retry;
0182 int err = 0;
0183
0184 if ((reg > 0x7f) || (value > 0x1ff)) {
0185 dev_err(emu->card->dev, "i2c_write: invalid values.\n");
0186 return -EINVAL;
0187 }
0188
0189
0190 spin_lock(&emu->i2c_lock);
0191
0192 tmp = reg << 25 | value << 16;
0193
0194
0195 snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
0196 tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0);
0197
0198 for (retry = 0; retry < 10; retry++) {
0199
0200 tmp = 0;
0201 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
0202 snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
0203
0204
0205 while (1) {
0206 mdelay(1);
0207 status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
0208 timeout++;
0209 if ((status & I2C_A_ADC_START) == 0)
0210 break;
0211
0212 if (timeout > 1000) {
0213 dev_warn(emu->card->dev,
0214 "emu10k1:I2C:timeout status=0x%x\n",
0215 status);
0216 break;
0217 }
0218 }
0219
0220 if ((status & I2C_A_ADC_ABORT) == 0)
0221 break;
0222 }
0223
0224 if (retry == 10) {
0225 dev_err(emu->card->dev, "Writing to ADC failed!\n");
0226 dev_err(emu->card->dev, "status=0x%x, reg=%d, value=%d\n",
0227 status, reg, value);
0228
0229 err = -EINVAL;
0230 }
0231
0232 spin_unlock(&emu->i2c_lock);
0233 return err;
0234 }
0235
0236 int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
0237 {
0238 unsigned long flags;
0239
0240 if (reg > 0x3f)
0241 return 1;
0242 reg += 0x40;
0243 if (value > 0x3f)
0244 return 1;
0245 spin_lock_irqsave(&emu->emu_lock, flags);
0246 outl(reg, emu->port + A_IOCFG);
0247 udelay(10);
0248 outl(reg | 0x80, emu->port + A_IOCFG);
0249 udelay(10);
0250 outl(value, emu->port + A_IOCFG);
0251 udelay(10);
0252 outl(value | 0x80 , emu->port + A_IOCFG);
0253 spin_unlock_irqrestore(&emu->emu_lock, flags);
0254
0255 return 0;
0256 }
0257
0258 int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value)
0259 {
0260 unsigned long flags;
0261 if (reg > 0x3f)
0262 return 1;
0263 reg += 0x40;
0264 spin_lock_irqsave(&emu->emu_lock, flags);
0265 outl(reg, emu->port + A_IOCFG);
0266 udelay(10);
0267 outl(reg | 0x80, emu->port + A_IOCFG);
0268 udelay(10);
0269 *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
0270 spin_unlock_irqrestore(&emu->emu_lock, flags);
0271
0272 return 0;
0273 }
0274
0275
0276
0277
0278 int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src)
0279 {
0280 snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
0281 snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
0282 snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
0283 snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
0284
0285 return 0;
0286 }
0287
0288 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
0289 {
0290 unsigned long flags;
0291 unsigned int enable;
0292
0293 spin_lock_irqsave(&emu->emu_lock, flags);
0294 enable = inl(emu->port + INTE) | intrenb;
0295 outl(enable, emu->port + INTE);
0296 spin_unlock_irqrestore(&emu->emu_lock, flags);
0297 }
0298
0299 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
0300 {
0301 unsigned long flags;
0302 unsigned int enable;
0303
0304 spin_lock_irqsave(&emu->emu_lock, flags);
0305 enable = inl(emu->port + INTE) & ~intrenb;
0306 outl(enable, emu->port + INTE);
0307 spin_unlock_irqrestore(&emu->emu_lock, flags);
0308 }
0309
0310 void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
0311 {
0312 unsigned long flags;
0313 unsigned int val;
0314
0315 spin_lock_irqsave(&emu->emu_lock, flags);
0316
0317 if (voicenum >= 32) {
0318 outl(CLIEH << 16, emu->port + PTR);
0319 val = inl(emu->port + DATA);
0320 val |= 1 << (voicenum - 32);
0321 } else {
0322 outl(CLIEL << 16, emu->port + PTR);
0323 val = inl(emu->port + DATA);
0324 val |= 1 << voicenum;
0325 }
0326 outl(val, emu->port + DATA);
0327 spin_unlock_irqrestore(&emu->emu_lock, flags);
0328 }
0329
0330 void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
0331 {
0332 unsigned long flags;
0333 unsigned int val;
0334
0335 spin_lock_irqsave(&emu->emu_lock, flags);
0336
0337 if (voicenum >= 32) {
0338 outl(CLIEH << 16, emu->port + PTR);
0339 val = inl(emu->port + DATA);
0340 val &= ~(1 << (voicenum - 32));
0341 } else {
0342 outl(CLIEL << 16, emu->port + PTR);
0343 val = inl(emu->port + DATA);
0344 val &= ~(1 << voicenum);
0345 }
0346 outl(val, emu->port + DATA);
0347 spin_unlock_irqrestore(&emu->emu_lock, flags);
0348 }
0349
0350 void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
0351 {
0352 unsigned long flags;
0353
0354 spin_lock_irqsave(&emu->emu_lock, flags);
0355
0356 if (voicenum >= 32) {
0357 outl(CLIPH << 16, emu->port + PTR);
0358 voicenum = 1 << (voicenum - 32);
0359 } else {
0360 outl(CLIPL << 16, emu->port + PTR);
0361 voicenum = 1 << voicenum;
0362 }
0363 outl(voicenum, emu->port + DATA);
0364 spin_unlock_irqrestore(&emu->emu_lock, flags);
0365 }
0366
0367 void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
0368 {
0369 unsigned long flags;
0370 unsigned int val;
0371
0372 spin_lock_irqsave(&emu->emu_lock, flags);
0373
0374 if (voicenum >= 32) {
0375 outl(HLIEH << 16, emu->port + PTR);
0376 val = inl(emu->port + DATA);
0377 val |= 1 << (voicenum - 32);
0378 } else {
0379 outl(HLIEL << 16, emu->port + PTR);
0380 val = inl(emu->port + DATA);
0381 val |= 1 << voicenum;
0382 }
0383 outl(val, emu->port + DATA);
0384 spin_unlock_irqrestore(&emu->emu_lock, flags);
0385 }
0386
0387 void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
0388 {
0389 unsigned long flags;
0390 unsigned int val;
0391
0392 spin_lock_irqsave(&emu->emu_lock, flags);
0393
0394 if (voicenum >= 32) {
0395 outl(HLIEH << 16, emu->port + PTR);
0396 val = inl(emu->port + DATA);
0397 val &= ~(1 << (voicenum - 32));
0398 } else {
0399 outl(HLIEL << 16, emu->port + PTR);
0400 val = inl(emu->port + DATA);
0401 val &= ~(1 << voicenum);
0402 }
0403 outl(val, emu->port + DATA);
0404 spin_unlock_irqrestore(&emu->emu_lock, flags);
0405 }
0406
0407 void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
0408 {
0409 unsigned long flags;
0410
0411 spin_lock_irqsave(&emu->emu_lock, flags);
0412
0413 if (voicenum >= 32) {
0414 outl(HLIPH << 16, emu->port + PTR);
0415 voicenum = 1 << (voicenum - 32);
0416 } else {
0417 outl(HLIPL << 16, emu->port + PTR);
0418 voicenum = 1 << voicenum;
0419 }
0420 outl(voicenum, emu->port + DATA);
0421 spin_unlock_irqrestore(&emu->emu_lock, flags);
0422 }
0423
0424 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
0425 {
0426 unsigned long flags;
0427 unsigned int sol;
0428
0429 spin_lock_irqsave(&emu->emu_lock, flags);
0430
0431 if (voicenum >= 32) {
0432 outl(SOLEH << 16, emu->port + PTR);
0433 sol = inl(emu->port + DATA);
0434 sol |= 1 << (voicenum - 32);
0435 } else {
0436 outl(SOLEL << 16, emu->port + PTR);
0437 sol = inl(emu->port + DATA);
0438 sol |= 1 << voicenum;
0439 }
0440 outl(sol, emu->port + DATA);
0441 spin_unlock_irqrestore(&emu->emu_lock, flags);
0442 }
0443
0444 void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
0445 {
0446 unsigned long flags;
0447 unsigned int sol;
0448
0449 spin_lock_irqsave(&emu->emu_lock, flags);
0450
0451 if (voicenum >= 32) {
0452 outl(SOLEH << 16, emu->port + PTR);
0453 sol = inl(emu->port + DATA);
0454 sol &= ~(1 << (voicenum - 32));
0455 } else {
0456 outl(SOLEL << 16, emu->port + PTR);
0457 sol = inl(emu->port + DATA);
0458 sol &= ~(1 << voicenum);
0459 }
0460 outl(sol, emu->port + DATA);
0461 spin_unlock_irqrestore(&emu->emu_lock, flags);
0462 }
0463
0464 void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
0465 {
0466 volatile unsigned count;
0467 unsigned int newtime = 0, curtime;
0468
0469 curtime = inl(emu->port + WC) >> 6;
0470 while (wait-- > 0) {
0471 count = 0;
0472 while (count++ < 16384) {
0473 newtime = inl(emu->port + WC) >> 6;
0474 if (newtime != curtime)
0475 break;
0476 }
0477 if (count > 16384)
0478 break;
0479 curtime = newtime;
0480 }
0481 }
0482
0483 unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
0484 {
0485 struct snd_emu10k1 *emu = ac97->private_data;
0486 unsigned long flags;
0487 unsigned short val;
0488
0489 spin_lock_irqsave(&emu->emu_lock, flags);
0490 outb(reg, emu->port + AC97ADDRESS);
0491 val = inw(emu->port + AC97DATA);
0492 spin_unlock_irqrestore(&emu->emu_lock, flags);
0493 return val;
0494 }
0495
0496 void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)
0497 {
0498 struct snd_emu10k1 *emu = ac97->private_data;
0499 unsigned long flags;
0500
0501 spin_lock_irqsave(&emu->emu_lock, flags);
0502 outb(reg, emu->port + AC97ADDRESS);
0503 outw(data, emu->port + AC97DATA);
0504 spin_unlock_irqrestore(&emu->emu_lock, flags);
0505 }
0506
0507
0508
0509
0510
0511 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
0512 {
0513 static const u32 logMagTable[128] = {
0514 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
0515 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
0516 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
0517 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
0518 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
0519 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
0520 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
0521 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
0522 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
0523 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
0524 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
0525 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
0526 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
0527 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
0528 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
0529 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
0530 };
0531 static const char logSlopeTable[128] = {
0532 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
0533 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
0534 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
0535 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
0536 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
0537 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
0538 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
0539 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
0540 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
0541 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
0542 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
0543 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
0544 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
0545 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
0546 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
0547 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
0548 };
0549 int i;
0550
0551 if (rate == 0)
0552 return 0;
0553 rate *= 11185;
0554 for (i = 31; i > 0; i--) {
0555 if (rate & 0x80000000) {
0556 return (((unsigned int) (i - 15) << 20) +
0557 logMagTable[0x7f & (rate >> 24)] +
0558 (0x7f & (rate >> 17)) *
0559 logSlopeTable[0x7f & (rate >> 24)]);
0560 }
0561 rate <<= 1;
0562 }
0563
0564 return 0;
0565 }
0566