772 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>4 * Lee Revell <rlrevell@joe-job.com>5 * James Courtier-Dutton <James@superbug.co.uk>6 * Oswald Buddenhagen <oswald.buddenhagen@gmx.de>7 * Creative Labs, Inc.8 *9 * Routines for control of EMU10K1 chips10 */11 12#include <linux/time.h>13#include <sound/core.h>14#include <sound/emu10k1.h>15#include <linux/delay.h>16#include <linux/export.h>17#include "p17v.h"18 19static inline bool check_ptr_reg(struct snd_emu10k1 *emu, unsigned int reg)20{21 if (snd_BUG_ON(!emu))22 return false;23 if (snd_BUG_ON(reg & (emu->audigy ? (0xffff0000 & ~A_PTR_ADDRESS_MASK)24 : (0xffff0000 & ~PTR_ADDRESS_MASK))))25 return false;26 if (snd_BUG_ON(reg & 0x0000ffff & ~PTR_CHANNELNUM_MASK))27 return false;28 return true;29}30 31unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)32{33 unsigned long flags;34 unsigned int regptr, val;35 unsigned int mask;36 37 regptr = (reg << 16) | chn;38 if (!check_ptr_reg(emu, regptr))39 return 0;40 41 spin_lock_irqsave(&emu->emu_lock, flags);42 outl(regptr, emu->port + PTR);43 val = inl(emu->port + DATA);44 spin_unlock_irqrestore(&emu->emu_lock, flags);45 46 if (reg & 0xff000000) {47 unsigned char size, offset;48 49 size = (reg >> 24) & 0x3f;50 offset = (reg >> 16) & 0x1f;51 mask = (1 << size) - 1;52 53 return (val >> offset) & mask;54 } else {55 return val;56 }57}58 59EXPORT_SYMBOL(snd_emu10k1_ptr_read);60 61void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)62{63 unsigned int regptr;64 unsigned long flags;65 unsigned int mask;66 67 regptr = (reg << 16) | chn;68 if (!check_ptr_reg(emu, regptr))69 return;70 71 if (reg & 0xff000000) {72 unsigned char size, offset;73 74 size = (reg >> 24) & 0x3f;75 offset = (reg >> 16) & 0x1f;76 mask = (1 << size) - 1;77 if (snd_BUG_ON(data & ~mask))78 return;79 mask <<= offset;80 data <<= offset;81 82 spin_lock_irqsave(&emu->emu_lock, flags);83 outl(regptr, emu->port + PTR);84 data |= inl(emu->port + DATA) & ~mask;85 } else {86 spin_lock_irqsave(&emu->emu_lock, flags);87 outl(regptr, emu->port + PTR);88 }89 outl(data, emu->port + DATA);90 spin_unlock_irqrestore(&emu->emu_lock, flags);91}92 93EXPORT_SYMBOL(snd_emu10k1_ptr_write);94 95void snd_emu10k1_ptr_write_multiple(struct snd_emu10k1 *emu, unsigned int chn, ...)96{97 va_list va;98 u32 addr_mask;99 unsigned long flags;100 101 if (snd_BUG_ON(!emu))102 return;103 if (snd_BUG_ON(chn & ~PTR_CHANNELNUM_MASK))104 return;105 addr_mask = ~((emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK) >> 16);106 107 va_start(va, chn);108 spin_lock_irqsave(&emu->emu_lock, flags);109 for (;;) {110 u32 data;111 u32 reg = va_arg(va, u32);112 if (reg == REGLIST_END)113 break;114 data = va_arg(va, u32);115 if (snd_BUG_ON(reg & addr_mask)) // Only raw registers supported here116 continue;117 outl((reg << 16) | chn, emu->port + PTR);118 outl(data, emu->port + DATA);119 }120 spin_unlock_irqrestore(&emu->emu_lock, flags);121 va_end(va);122}123 124EXPORT_SYMBOL(snd_emu10k1_ptr_write_multiple);125 126unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, 127 unsigned int reg, 128 unsigned int chn)129{130 unsigned long flags;131 unsigned int regptr, val;132 133 regptr = (reg << 16) | chn;134 135 spin_lock_irqsave(&emu->emu_lock, flags);136 outl(regptr, emu->port + PTR2);137 val = inl(emu->port + DATA2);138 spin_unlock_irqrestore(&emu->emu_lock, flags);139 return val;140}141 142void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, 143 unsigned int reg, 144 unsigned int chn, 145 unsigned int data)146{147 unsigned int regptr;148 unsigned long flags;149 150 regptr = (reg << 16) | chn;151 152 spin_lock_irqsave(&emu->emu_lock, flags);153 outl(regptr, emu->port + PTR2);154 outl(data, emu->port + DATA2);155 spin_unlock_irqrestore(&emu->emu_lock, flags);156}157 158int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,159 unsigned int data)160{161 unsigned int reset, set;162 unsigned int reg, tmp;163 int n, result;164 int err = 0;165 166 /* This function is not re-entrant, so protect against it. */167 spin_lock(&emu->spi_lock);168 if (emu->card_capabilities->ca0108_chip)169 reg = P17V_SPI;170 else {171 /* For other chip types the SPI register172 * is currently unknown. */173 err = 1;174 goto spi_write_exit;175 }176 if (data > 0xffff) {177 /* Only 16bit values allowed */178 err = 1;179 goto spi_write_exit;180 }181 182 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);183 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */184 set = reset | 0x10000; /* Set xxx1xxxx */185 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);186 tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */187 snd_emu10k1_ptr20_write(emu, reg, 0, set | data);188 result = 1;189 /* Wait for status bit to return to 0 */190 for (n = 0; n < 100; n++) {191 udelay(10);192 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);193 if (!(tmp & 0x10000)) {194 result = 0;195 break;196 }197 }198 if (result) {199 /* Timed out */200 err = 1;201 goto spi_write_exit;202 }203 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);204 tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */205 err = 0;206spi_write_exit:207 spin_unlock(&emu->spi_lock);208 return err;209}210 211/* The ADC does not support i2c read, so only write is implemented */212int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,213 u32 reg,214 u32 value)215{216 u32 tmp;217 int timeout = 0;218 int status;219 int retry;220 int err = 0;221 222 if ((reg > 0x7f) || (value > 0x1ff)) {223 dev_err(emu->card->dev, "i2c_write: invalid values.\n");224 return -EINVAL;225 }226 227 /* This function is not re-entrant, so protect against it. */228 spin_lock(&emu->i2c_lock);229 230 tmp = reg << 25 | value << 16;231 232 /* This controls the I2C connected to the WM8775 ADC Codec */233 snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);234 tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */235 236 for (retry = 0; retry < 10; retry++) {237 /* Send the data to i2c */238 tmp = 0;239 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);240 snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);241 242 /* Wait till the transaction ends */243 while (1) {244 mdelay(1);245 status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);246 timeout++;247 if ((status & I2C_A_ADC_START) == 0)248 break;249 250 if (timeout > 1000) {251 dev_warn(emu->card->dev,252 "emu10k1:I2C:timeout status=0x%x\n",253 status);254 break;255 }256 }257 //Read back and see if the transaction is successful258 if ((status & I2C_A_ADC_ABORT) == 0)259 break;260 }261 262 if (retry == 10) {263 dev_err(emu->card->dev, "Writing to ADC failed!\n");264 dev_err(emu->card->dev, "status=0x%x, reg=%d, value=%d\n",265 status, reg, value);266 /* dump_stack(); */267 err = -EINVAL;268 }269 270 spin_unlock(&emu->i2c_lock);271 return err;272}273 274static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32 value)275{276 if (snd_BUG_ON(reg > 0x3f))277 return;278 reg += 0x40; /* 0x40 upwards are registers. */279 if (snd_BUG_ON(value > 0x3f)) /* 0 to 0x3f are values */280 return;281 outw(reg, emu->port + A_GPIO);282 udelay(10);283 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */284 udelay(10);285 outw(value, emu->port + A_GPIO);286 udelay(10);287 outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */288 udelay(10);289}290 291void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)292{293 if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))294 return;295 snd_emu1010_fpga_write_locked(emu, reg, value);296}297 298void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value)299{300 snd_emu1010_fpga_lock(emu);301 snd_emu1010_fpga_write_locked(emu, reg, value);302 snd_emu1010_fpga_unlock(emu);303}304 305void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)306{307 // The higest input pin is used as the designated interrupt trigger,308 // so it needs to be masked out.309 // But note that any other input pin change will also cause an IRQ,310 // so using this function often causes an IRQ as a side effect.311 u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;312 313 if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))314 return;315 if (snd_BUG_ON(reg > 0x3f))316 return;317 reg += 0x40; /* 0x40 upwards are registers. */318 outw(reg, emu->port + A_GPIO);319 udelay(10);320 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */321 udelay(10);322 *value = ((inw(emu->port + A_GPIO) >> 8) & mask);323}324 325/* Each Destination has one and only one Source,326 * but one Source can feed any number of Destinations simultaneously.327 */328void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src)329{330 if (snd_BUG_ON(dst & ~0x71f))331 return;332 if (snd_BUG_ON(src & ~0x71f))333 return;334 snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);335 snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);336 snd_emu1010_fpga_write(emu, EMU_HANA_SRCHI, src >> 8);337 snd_emu1010_fpga_write(emu, EMU_HANA_SRCLO, src & 0x1f);338}339 340u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst)341{342 u32 hi, lo;343 344 if (snd_BUG_ON(dst & ~0x71f))345 return 0;346 snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);347 snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);348 snd_emu1010_fpga_read(emu, EMU_HANA_SRCHI, &hi);349 snd_emu1010_fpga_read(emu, EMU_HANA_SRCLO, &lo);350 return (hi << 8) | lo;351}352 353int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src)354{355 u32 reg_lo, reg_hi, value, value2;356 357 switch (src) {358 case EMU_HANA_WCLOCK_HANA_SPDIF_IN:359 snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &value);360 if (value & EMU_HANA_SPDIF_MODE_RX_INVALID)361 return 0;362 reg_lo = EMU_HANA_WC_SPDIF_LO;363 reg_hi = EMU_HANA_WC_SPDIF_HI;364 break;365 case EMU_HANA_WCLOCK_HANA_ADAT_IN:366 reg_lo = EMU_HANA_WC_ADAT_LO;367 reg_hi = EMU_HANA_WC_ADAT_HI;368 break;369 case EMU_HANA_WCLOCK_SYNC_BNC:370 reg_lo = EMU_HANA_WC_BNC_LO;371 reg_hi = EMU_HANA_WC_BNC_HI;372 break;373 case EMU_HANA_WCLOCK_2ND_HANA:374 reg_lo = EMU_HANA2_WC_SPDIF_LO;375 reg_hi = EMU_HANA2_WC_SPDIF_HI;376 break;377 default:378 return 0;379 }380 snd_emu1010_fpga_read(emu, reg_hi, &value);381 snd_emu1010_fpga_read(emu, reg_lo, &value2);382 // FIXME: The /4 is valid for 0404b, but contradicts all other info.383 return 0x1770000 / 4 / (((value << 5) | value2) + 1);384}385 386void snd_emu1010_update_clock(struct snd_emu10k1 *emu)387{388 int clock;389 u32 leds;390 391 switch (emu->emu1010.wclock) {392 case EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X:393 clock = 44100;394 leds = EMU_HANA_DOCK_LEDS_2_44K;395 break;396 case EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X:397 clock = 48000;398 leds = EMU_HANA_DOCK_LEDS_2_48K;399 break;400 default:401 clock = snd_emu1010_get_raw_rate(402 emu, emu->emu1010.wclock & EMU_HANA_WCLOCK_SRC_MASK);403 // The raw rate reading is rather coarse (it cannot accurately404 // represent 44.1 kHz) and fluctuates slightly. Luckily, the405 // clock comes from digital inputs, which use standardized rates.406 // So we round to the closest standard rate and ignore discrepancies.407 if (clock < 46000) {408 clock = 44100;409 leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_44K;410 } else {411 clock = 48000;412 leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_48K;413 }414 break;415 }416 emu->emu1010.word_clock = clock;417 418 // FIXME: this should probably represent the AND of all currently419 // used sources' lock status. But we don't know how to get that ...420 leds |= EMU_HANA_DOCK_LEDS_2_LOCK;421 422 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, leds);423}424 425void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int dock,426 const struct firmware *fw_entry)427{428 __always_unused u16 write_post;429 430 // On E-MU 1010 rev1 the FPGA is a Xilinx Spartan IIE XC2S50E.431 // On E-MU 0404b it is a Xilinx Spartan III XC3S50.432 // The wiring is as follows:433 // GPO7 -> FPGA input & 1K resistor -> FPGA /PGMN <- FPGA output434 // In normal operation, the active low reset line is held up by435 // an FPGA output, while the GPO pin performs its duty as control436 // register access strobe signal. Writing the respective bit to437 // EMU_HANA_FPGA_CONFIG puts the FPGA output into high-Z mode, at438 // which point the GPO pin can control the reset line through the439 // resistor.440 // GPO6 -> FPGA CCLK & FPGA input441 // GPO5 -> FPGA DIN (dual function)442 443 // If the FPGA is already programmed, return it to programming mode444 snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,445 dock ? EMU_HANA_FPGA_CONFIG_AUDIODOCK :446 EMU_HANA_FPGA_CONFIG_HANA);447 448 // Assert reset line for 100uS449 outw(0x00, emu->port + A_GPIO);450 write_post = inw(emu->port + A_GPIO);451 udelay(100);452 outw(0x80, emu->port + A_GPIO);453 write_post = inw(emu->port + A_GPIO);454 udelay(100); // Allow FPGA memory to clean455 456 // Upload the netlist. Keep reset line high!457 for (int n = 0; n < fw_entry->size; n++) {458 u8 value = fw_entry->data[n];459 for (int i = 0; i < 8; i++) {460 u16 reg = 0x80;461 if (value & 1)462 reg |= 0x20;463 value >>= 1;464 outw(reg, emu->port + A_GPIO);465 write_post = inw(emu->port + A_GPIO);466 outw(reg | 0x40, emu->port + A_GPIO);467 write_post = inw(emu->port + A_GPIO);468 }469 }470 471 // After programming, set GPIO bit 4 high again.472 // This appears to be a config word that the rev1 Hana473 // firmware reads; weird things happen without this.474 outw(0x10, emu->port + A_GPIO);475 write_post = inw(emu->port + A_GPIO);476}477 478void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)479{480 unsigned long flags;481 unsigned int enable;482 483 spin_lock_irqsave(&emu->emu_lock, flags);484 enable = inl(emu->port + INTE) | intrenb;485 outl(enable, emu->port + INTE);486 spin_unlock_irqrestore(&emu->emu_lock, flags);487}488 489void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)490{491 unsigned long flags;492 unsigned int enable;493 494 spin_lock_irqsave(&emu->emu_lock, flags);495 enable = inl(emu->port + INTE) & ~intrenb;496 outl(enable, emu->port + INTE);497 spin_unlock_irqrestore(&emu->emu_lock, flags);498}499 500void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)501{502 unsigned long flags;503 unsigned int val;504 505 spin_lock_irqsave(&emu->emu_lock, flags);506 if (voicenum >= 32) {507 outl(CLIEH << 16, emu->port + PTR);508 val = inl(emu->port + DATA);509 val |= 1 << (voicenum - 32);510 } else {511 outl(CLIEL << 16, emu->port + PTR);512 val = inl(emu->port + DATA);513 val |= 1 << voicenum;514 }515 outl(val, emu->port + DATA);516 spin_unlock_irqrestore(&emu->emu_lock, flags);517}518 519void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)520{521 unsigned long flags;522 unsigned int val;523 524 spin_lock_irqsave(&emu->emu_lock, flags);525 if (voicenum >= 32) {526 outl(CLIEH << 16, emu->port + PTR);527 val = inl(emu->port + DATA);528 val &= ~(1 << (voicenum - 32));529 } else {530 outl(CLIEL << 16, emu->port + PTR);531 val = inl(emu->port + DATA);532 val &= ~(1 << voicenum);533 }534 outl(val, emu->port + DATA);535 spin_unlock_irqrestore(&emu->emu_lock, flags);536}537 538void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)539{540 unsigned long flags;541 542 spin_lock_irqsave(&emu->emu_lock, flags);543 if (voicenum >= 32) {544 outl(CLIPH << 16, emu->port + PTR);545 voicenum = 1 << (voicenum - 32);546 } else {547 outl(CLIPL << 16, emu->port + PTR);548 voicenum = 1 << voicenum;549 }550 outl(voicenum, emu->port + DATA);551 spin_unlock_irqrestore(&emu->emu_lock, flags);552}553 554void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)555{556 unsigned long flags;557 unsigned int val;558 559 spin_lock_irqsave(&emu->emu_lock, flags);560 if (voicenum >= 32) {561 outl(HLIEH << 16, emu->port + PTR);562 val = inl(emu->port + DATA);563 val |= 1 << (voicenum - 32);564 } else {565 outl(HLIEL << 16, emu->port + PTR);566 val = inl(emu->port + DATA);567 val |= 1 << voicenum;568 }569 outl(val, emu->port + DATA);570 spin_unlock_irqrestore(&emu->emu_lock, flags);571}572 573void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)574{575 unsigned long flags;576 unsigned int val;577 578 spin_lock_irqsave(&emu->emu_lock, flags);579 if (voicenum >= 32) {580 outl(HLIEH << 16, emu->port + PTR);581 val = inl(emu->port + DATA);582 val &= ~(1 << (voicenum - 32));583 } else {584 outl(HLIEL << 16, emu->port + PTR);585 val = inl(emu->port + DATA);586 val &= ~(1 << voicenum);587 }588 outl(val, emu->port + DATA);589 spin_unlock_irqrestore(&emu->emu_lock, flags);590}591 592void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)593{594 unsigned long flags;595 596 spin_lock_irqsave(&emu->emu_lock, flags);597 if (voicenum >= 32) {598 outl(HLIPH << 16, emu->port + PTR);599 voicenum = 1 << (voicenum - 32);600 } else {601 outl(HLIPL << 16, emu->port + PTR);602 voicenum = 1 << voicenum;603 }604 outl(voicenum, emu->port + DATA);605 spin_unlock_irqrestore(&emu->emu_lock, flags);606}607 608#if 0609void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)610{611 unsigned long flags;612 unsigned int sol;613 614 spin_lock_irqsave(&emu->emu_lock, flags);615 if (voicenum >= 32) {616 outl(SOLEH << 16, emu->port + PTR);617 sol = inl(emu->port + DATA);618 sol |= 1 << (voicenum - 32);619 } else {620 outl(SOLEL << 16, emu->port + PTR);621 sol = inl(emu->port + DATA);622 sol |= 1 << voicenum;623 }624 outl(sol, emu->port + DATA);625 spin_unlock_irqrestore(&emu->emu_lock, flags);626}627 628void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)629{630 unsigned long flags;631 unsigned int sol;632 633 spin_lock_irqsave(&emu->emu_lock, flags);634 if (voicenum >= 32) {635 outl(SOLEH << 16, emu->port + PTR);636 sol = inl(emu->port + DATA);637 sol &= ~(1 << (voicenum - 32));638 } else {639 outl(SOLEL << 16, emu->port + PTR);640 sol = inl(emu->port + DATA);641 sol &= ~(1 << voicenum);642 }643 outl(sol, emu->port + DATA);644 spin_unlock_irqrestore(&emu->emu_lock, flags);645}646#endif647 648void snd_emu10k1_voice_set_loop_stop_multiple(struct snd_emu10k1 *emu, u64 voices)649{650 unsigned long flags;651 652 spin_lock_irqsave(&emu->emu_lock, flags);653 outl(SOLEL << 16, emu->port + PTR);654 outl(inl(emu->port + DATA) | (u32)voices, emu->port + DATA);655 outl(SOLEH << 16, emu->port + PTR);656 outl(inl(emu->port + DATA) | (u32)(voices >> 32), emu->port + DATA);657 spin_unlock_irqrestore(&emu->emu_lock, flags);658}659 660void snd_emu10k1_voice_clear_loop_stop_multiple(struct snd_emu10k1 *emu, u64 voices)661{662 unsigned long flags;663 664 spin_lock_irqsave(&emu->emu_lock, flags);665 outl(SOLEL << 16, emu->port + PTR);666 outl(inl(emu->port + DATA) & (u32)~voices, emu->port + DATA);667 outl(SOLEH << 16, emu->port + PTR);668 outl(inl(emu->port + DATA) & (u32)(~voices >> 32), emu->port + DATA);669 spin_unlock_irqrestore(&emu->emu_lock, flags);670}671 672int snd_emu10k1_voice_clear_loop_stop_multiple_atomic(struct snd_emu10k1 *emu, u64 voices)673{674 unsigned long flags;675 u32 soll, solh;676 int ret = -EIO;677 678 spin_lock_irqsave(&emu->emu_lock, flags);679 680 outl(SOLEL << 16, emu->port + PTR);681 soll = inl(emu->port + DATA);682 outl(SOLEH << 16, emu->port + PTR);683 solh = inl(emu->port + DATA);684 685 soll &= (u32)~voices;686 solh &= (u32)(~voices >> 32);687 688 for (int tries = 0; tries < 1000; tries++) {689 const u32 quart = 1U << (REG_SIZE(WC_CURRENTCHANNEL) - 2);690 // First we wait for the third quarter of the sample cycle ...691 u32 wc = inl(emu->port + WC);692 u32 cc = REG_VAL_GET(WC_CURRENTCHANNEL, wc);693 if (cc >= quart * 2 && cc < quart * 3) {694 // ... and release the low voices, while the high ones are serviced.695 outl(SOLEL << 16, emu->port + PTR);696 outl(soll, emu->port + DATA);697 // Then we wait for the first quarter of the next sample cycle ...698 for (; tries < 1000; tries++) {699 cc = REG_VAL_GET(WC_CURRENTCHANNEL, inl(emu->port + WC));700 if (cc < quart)701 goto good;702 // We will block for 10+ us with interrupts disabled. This is703 // not nice at all, but necessary for reasonable reliability.704 udelay(1);705 }706 break;707 good:708 // ... and release the high voices, while the low ones are serviced.709 outl(SOLEH << 16, emu->port + PTR);710 outl(solh, emu->port + DATA);711 // Finally we verify that nothing interfered in fact.712 if (REG_VAL_GET(WC_SAMPLECOUNTER, inl(emu->port + WC)) ==713 ((REG_VAL_GET(WC_SAMPLECOUNTER, wc) + 1) & REG_MASK0(WC_SAMPLECOUNTER))) {714 ret = 0;715 } else {716 ret = -EAGAIN;717 }718 break;719 }720 // Don't block for too long721 spin_unlock_irqrestore(&emu->emu_lock, flags);722 udelay(1);723 spin_lock_irqsave(&emu->emu_lock, flags);724 }725 726 spin_unlock_irqrestore(&emu->emu_lock, flags);727 return ret;728}729 730void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)731{732 volatile unsigned count;733 unsigned int newtime = 0, curtime;734 735 curtime = inl(emu->port + WC) >> 6;736 while (wait-- > 0) {737 count = 0;738 while (count++ < 16384) {739 newtime = inl(emu->port + WC) >> 6;740 if (newtime != curtime)741 break;742 }743 if (count > 16384)744 break;745 curtime = newtime;746 }747}748 749unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)750{751 struct snd_emu10k1 *emu = ac97->private_data;752 unsigned long flags;753 unsigned short val;754 755 spin_lock_irqsave(&emu->emu_lock, flags);756 outb(reg, emu->port + AC97ADDRESS);757 val = inw(emu->port + AC97DATA);758 spin_unlock_irqrestore(&emu->emu_lock, flags);759 return val;760}761 762void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)763{764 struct snd_emu10k1 *emu = ac97->private_data;765 unsigned long flags;766 767 spin_lock_irqsave(&emu->emu_lock, flags);768 outb(reg, emu->port + AC97ADDRESS);769 outw(data, emu->port + AC97DATA);770 spin_unlock_irqrestore(&emu->emu_lock, flags);771}772