brintos

brintos / linux-shallow public Read only

0
0
Text · 20.7 KiB · b60ab56 Raw
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