Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *                   Creative Labs, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Routines for control of EMU10K1 chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  BUGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *    --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *  TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *    --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <sound/emu10k1.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "p17v.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	unsigned int regptr, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	if (reg & 0xff000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		unsigned char size, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		size = (reg >> 24) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		offset = (reg >> 16) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		mask = ((1 << size) - 1) << offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		outl(regptr, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		return (val & mask) >> offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		outl(regptr, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) EXPORT_SYMBOL(snd_emu10k1_ptr_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	unsigned int regptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	if (snd_BUG_ON(!emu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	if (reg & 0xff000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		unsigned char size, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		size = (reg >> 24) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		offset = (reg >> 16) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		mask = ((1 << size) - 1) << offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		data = (data << offset) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		outl(regptr, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		data |= inl(emu->port + DATA) & ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		outl(data, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		spin_unlock_irqrestore(&emu->emu_lock, flags);		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		outl(regptr, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		outl(data, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) EXPORT_SYMBOL(snd_emu10k1_ptr_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 					  unsigned int reg, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 					  unsigned int chn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	unsigned int regptr, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	regptr = (reg << 16) | chn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	outl(regptr, emu->port + 0x20 + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	val = inl(emu->port + 0x20 + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 				   unsigned int reg, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 				   unsigned int chn, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 				   unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	unsigned int regptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	regptr = (reg << 16) | chn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	outl(regptr, emu->port + 0x20 + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	outl(data, emu->port + 0x20 + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 				   unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	unsigned int reset, set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	unsigned int reg, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	int n, result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	/* This function is not re-entrant, so protect against it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	spin_lock(&emu->spi_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (emu->card_capabilities->ca0108_chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		reg = 0x3c; /* PTR20, reg 0x3c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		/* For other chip types the SPI register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		 * is currently unknown. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		err = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		goto spi_write_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	if (data > 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		/* Only 16bit values allowed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		err = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		goto spi_write_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	set = reset | 0x10000; /* Set xxx1xxxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	result = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	/* Wait for status bit to return to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	for (n = 0; n < 100; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		if (!(tmp & 0x10000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		/* Timed out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		err = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		goto spi_write_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) spi_write_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	spin_unlock(&emu->spi_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* The ADC does not support i2c read, so only write is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 				u32 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 				u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	int timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	int retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	if ((reg > 0x7f) || (value > 0x1ff)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		dev_err(emu->card->dev, "i2c_write: invalid values.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	/* This function is not re-entrant, so protect against it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	spin_lock(&emu->i2c_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	tmp = reg << 25 | value << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	/* This controls the I2C connected to the WM8775 ADC Codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	for (retry = 0; retry < 10; retry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		/* Send the data to i2c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		/* Wait till the transaction ends */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 			mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			timeout++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			if ((status & I2C_A_ADC_START) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			if (timeout > 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 				dev_warn(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 					   "emu10k1:I2C:timeout status=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 					   status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		//Read back and see if the transaction is successful
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		if ((status & I2C_A_ADC_ABORT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	if (retry == 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		dev_err(emu->card->dev, "Writing to ADC failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		dev_err(emu->card->dev, "status=0x%x, reg=%d, value=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			status, reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		/* dump_stack(); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	spin_unlock(&emu->i2c_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	if (reg > 0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	reg += 0x40; /* 0x40 upwards are registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (value > 0x3f) /* 0 to 0x3f are values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	outl(reg, emu->port + A_IOCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	outl(value, emu->port + A_IOCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	if (reg > 0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	reg += 0x40; /* 0x40 upwards are registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	outl(reg, emu->port + A_IOCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	*value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Each Destination has one and only one Source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * but one Source can feed any number of Destinations simultaneously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	unsigned int enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	enable = inl(emu->port + INTE) | intrenb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	outl(enable, emu->port + INTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	unsigned int enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	enable = inl(emu->port + INTE) & ~intrenb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	outl(enable, emu->port + INTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		outl(CLIEH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		val |= 1 << (voicenum - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		outl(CLIEL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		val |= 1 << voicenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	outl(val, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		outl(CLIEH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		val &= ~(1 << (voicenum - 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		outl(CLIEL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		val &= ~(1 << voicenum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	outl(val, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		outl(CLIPH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		voicenum = 1 << (voicenum - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		outl(CLIPL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		voicenum = 1 << voicenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	outl(voicenum, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		outl(HLIEH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		val |= 1 << (voicenum - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		outl(HLIEL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		val |= 1 << voicenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	outl(val, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		outl(HLIEH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		val &= ~(1 << (voicenum - 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		outl(HLIEL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		val = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		val &= ~(1 << voicenum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	outl(val, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		outl(HLIPH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		voicenum = 1 << (voicenum - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		outl(HLIPL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		voicenum = 1 << voicenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	outl(voicenum, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	unsigned int sol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		outl(SOLEH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		sol = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		sol |= 1 << (voicenum - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		outl(SOLEL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		sol = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		sol |= 1 << voicenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	outl(sol, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	unsigned int sol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	/* voice interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	if (voicenum >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		outl(SOLEH << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		sol = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		sol &= ~(1 << (voicenum - 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		outl(SOLEL << 16, emu->port + PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		sol = inl(emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		sol &= ~(1 << voicenum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	outl(sol, emu->port + DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	volatile unsigned count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	unsigned int newtime = 0, curtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	curtime = inl(emu->port + WC) >> 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	while (wait-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		while (count++ < 16384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 			newtime = inl(emu->port + WC) >> 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 			if (newtime != curtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		if (count > 16384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		curtime = newtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	struct snd_emu10k1 *emu = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	outb(reg, emu->port + AC97ADDRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	val = inw(emu->port + AC97DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	struct snd_emu10k1 *emu = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	spin_lock_irqsave(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	outb(reg, emu->port + AC97ADDRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	outw(data, emu->port + AC97DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	spin_unlock_irqrestore(&emu->emu_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)  *  convert rate to pitch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	static const u32 logMagTable[128] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 		0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	static const char logSlopeTable[128] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	if (rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		return 0;	/* Bail out if no leading "1" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	rate *= 11185;		/* Scale 48000 to 0x20002380 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	for (i = 31; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		if (rate & 0x80000000) {	/* Detect leading "1" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 			return (((unsigned int) (i - 15) << 20) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			       logMagTable[0x7f & (rate >> 24)] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 					(0x7f & (rate >> 17)) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 					logSlopeTable[0x7f & (rate >> 24)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		rate <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	return 0;		/* Should never reach this point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)