File Index
Files and directories
Sign in
FILE

emu8000.c

File preview with syntax highlighting.

linux-6.19.14/sound/isa/sb/emu8000.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   4 *     and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
   5 *  Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
   6 *
   7 *  Routines for control of EMU8000 chip
   8 */
   9
  10#include <linux/wait.h>
  11#include <linux/sched/signal.h>
  12#include <linux/slab.h>
  13#include <linux/ioport.h>
  14#include <linux/export.h>
  15#include <linux/delay.h>
  16#include <linux/io.h>
  17#include <linux/string.h>
  18#include <sound/core.h>
  19#include <sound/emu8000.h>
  20#include <sound/emu8000_reg.h>
  21#include <linux/uaccess.h>
  22#include <linux/init.h>
  23#include <sound/control.h>
  24#include <sound/initval.h>
  25
  26/*
  27 * emu8000 register controls
  28 */
  29
  30/*
  31 * The following routines read and write registers on the emu8000.  They
  32 * should always be called via the EMU8000*READ/WRITE macros and never
  33 * directly.  The macros handle the port number and command word.
  34 */
  35/* Write a word */
  36void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
  37{
  38	guard(spinlock_irqsave)(&emu->reg_lock);
  39	if (reg != emu->last_reg) {
  40		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  41		emu->last_reg = reg;
  42	}
  43	outw((unsigned short)val, port); /* Send data */
  44}
  45
  46/* Read a word */
  47unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
  48{
  49	guard(spinlock_irqsave)(&emu->reg_lock);
  50	if (reg != emu->last_reg) {
  51		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  52		emu->last_reg = reg;
  53	}
  54	return inw(port);	/* Read data */
  55}
  56
  57/* Write a double word */
  58void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
  59{
  60	guard(spinlock_irqsave)(&emu->reg_lock);
  61	if (reg != emu->last_reg) {
  62		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  63		emu->last_reg = reg;
  64	}
  65	outw((unsigned short)val, port); /* Send low word of data */
  66	outw((unsigned short)(val>>16), port+2); /* Send high word of data */
  67}
  68
  69/* Read a double word */
  70unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
  71{
  72	unsigned short low;
  73
  74	guard(spinlock_irqsave)(&emu->reg_lock);
  75	if (reg != emu->last_reg) {
  76		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  77		emu->last_reg = reg;
  78	}
  79	low = inw(port);	/* Read low word of data */
  80	return low + (inw(port+2) << 16);
  81}
  82
  83/*
  84 * Set up / close a channel to be used for DMA.
  85 */
  86/*exported*/ void
  87snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
  88{
  89	unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0;
  90	mode &= EMU8000_RAM_MODE_MASK;
  91	if (mode == EMU8000_RAM_CLOSE) {
  92		EMU8000_CCCA_WRITE(emu, ch, 0);
  93		EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F);
  94		return;
  95	}
  96	EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
  97	EMU8000_VTFT_WRITE(emu, ch, 0);
  98	EMU8000_CVCF_WRITE(emu, ch, 0);
  99	EMU8000_PTRX_WRITE(emu, ch, 0x40000000);
 100	EMU8000_CPF_WRITE(emu, ch, 0x40000000);
 101	EMU8000_PSST_WRITE(emu, ch, 0);
 102	EMU8000_CSL_WRITE(emu, ch, 0);
 103	if (mode == EMU8000_RAM_WRITE) /* DMA write */
 104		EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit);
 105	else	   /* DMA read */
 106		EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit);
 107}
 108
 109/*
 110 */
 111static void
 112snd_emu8000_read_wait(struct snd_emu8000 *emu)
 113{
 114	while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
 115		schedule_timeout_interruptible(1);
 116		if (signal_pending(current))
 117			break;
 118	}
 119}
 120
 121/*
 122 */
 123static void
 124snd_emu8000_write_wait(struct snd_emu8000 *emu)
 125{
 126	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
 127		schedule_timeout_interruptible(1);
 128		if (signal_pending(current))
 129			break;
 130	}
 131}
 132
 133/*
 134 * detect a card at the given port
 135 */
 136static int
 137snd_emu8000_detect(struct snd_emu8000 *emu)
 138{
 139	/* Initialise */
 140	EMU8000_HWCF1_WRITE(emu, 0x0059);
 141	EMU8000_HWCF2_WRITE(emu, 0x0020);
 142	EMU8000_HWCF3_WRITE(emu, 0x0000);
 143	/* Check for a recognisable emu8000 */
 144	/*
 145	if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c)
 146		return -ENODEV;
 147		*/
 148	if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058)
 149		return -ENODEV;
 150	if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003)
 151		return -ENODEV;
 152
 153	dev_dbg(emu->card->dev, "EMU8000 [0x%lx]: Synth chip found\n",
 154		emu->port1);
 155	return 0;
 156}
 157
 158
 159/*
 160 * intiailize audio channels
 161 */
 162static void
 163init_audio(struct snd_emu8000 *emu)
 164{
 165	int ch;
 166
 167	/* turn off envelope engines */
 168	for (ch = 0; ch < EMU8000_CHANNELS; ch++)
 169		EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
 170  
 171	/* reset all other parameters to zero */
 172	for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
 173		EMU8000_ENVVOL_WRITE(emu, ch, 0);
 174		EMU8000_ENVVAL_WRITE(emu, ch, 0);
 175		EMU8000_DCYSUS_WRITE(emu, ch, 0);
 176		EMU8000_ATKHLDV_WRITE(emu, ch, 0);
 177		EMU8000_LFO1VAL_WRITE(emu, ch, 0);
 178		EMU8000_ATKHLD_WRITE(emu, ch, 0);
 179		EMU8000_LFO2VAL_WRITE(emu, ch, 0);
 180		EMU8000_IP_WRITE(emu, ch, 0);
 181		EMU8000_IFATN_WRITE(emu, ch, 0);
 182		EMU8000_PEFE_WRITE(emu, ch, 0);
 183		EMU8000_FMMOD_WRITE(emu, ch, 0);
 184		EMU8000_TREMFRQ_WRITE(emu, ch, 0);
 185		EMU8000_FM2FRQ2_WRITE(emu, ch, 0);
 186		EMU8000_PTRX_WRITE(emu, ch, 0);
 187		EMU8000_VTFT_WRITE(emu, ch, 0);
 188		EMU8000_PSST_WRITE(emu, ch, 0);
 189		EMU8000_CSL_WRITE(emu, ch, 0);
 190		EMU8000_CCCA_WRITE(emu, ch, 0);
 191	}
 192
 193	for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
 194		EMU8000_CPF_WRITE(emu, ch, 0);
 195		EMU8000_CVCF_WRITE(emu, ch, 0);
 196	}
 197}
 198
 199
 200/*
 201 * initialize DMA address
 202 */
 203static void
 204init_dma(struct snd_emu8000 *emu)
 205{
 206	EMU8000_SMALR_WRITE(emu, 0);
 207	EMU8000_SMARR_WRITE(emu, 0);
 208	EMU8000_SMALW_WRITE(emu, 0);
 209	EMU8000_SMARW_WRITE(emu, 0);
 210}
 211
 212/*
 213 * initialization arrays; from ADIP
 214 */
 215static const unsigned short init1[128] = {
 216	0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
 217	0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
 218	0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
 219	0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
 220
 221	0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
 222	0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
 223	0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
 224	0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
 225
 226	0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
 227	0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
 228	0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
 229	0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
 230
 231	0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
 232	0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
 233	0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
 234	0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
 235};
 236
 237static const unsigned short init2[128] = {
 238	0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
 239	0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
 240	0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
 241	0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
 242
 243	0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
 244	0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
 245	0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
 246	0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
 247
 248	0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
 249	0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
 250	0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
 251	0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
 252
 253	0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
 254	0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
 255	0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
 256	0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
 257};
 258
 259static const unsigned short init3[128] = {
 260	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
 261	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
 262	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
 263	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
 264
 265	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
 266	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
 267	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
 268	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
 269
 270	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
 271	0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
 272	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
 273	0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
 274
 275	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
 276	0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
 277	0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
 278	0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
 279};
 280
 281static const unsigned short init4[128] = {
 282	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
 283	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
 284	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
 285	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
 286
 287	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
 288	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
 289	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
 290	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
 291
 292	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
 293	0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
 294	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
 295	0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
 296
 297	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
 298	0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
 299	0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
 300	0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
 301};
 302
 303/* send an initialization array
 304 * Taken from the oss driver, not obvious from the doc how this
 305 * is meant to work
 306 */
 307static void
 308send_array(struct snd_emu8000 *emu, const unsigned short *data, int size)
 309{
 310	int i;
 311	const unsigned short *p;
 312
 313	p = data;
 314	for (i = 0; i < size; i++, p++)
 315		EMU8000_INIT1_WRITE(emu, i, *p);
 316	for (i = 0; i < size; i++, p++)
 317		EMU8000_INIT2_WRITE(emu, i, *p);
 318	for (i = 0; i < size; i++, p++)
 319		EMU8000_INIT3_WRITE(emu, i, *p);
 320	for (i = 0; i < size; i++, p++)
 321		EMU8000_INIT4_WRITE(emu, i, *p);
 322}
 323
 324
 325/*
 326 * Send initialization arrays to start up, this just follows the
 327 * initialisation sequence in the adip.
 328 */
 329static void
 330init_arrays(struct snd_emu8000 *emu)
 331{
 332	send_array(emu, init1, ARRAY_SIZE(init1)/4);
 333
 334	msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
 335	send_array(emu, init2, ARRAY_SIZE(init2)/4);
 336	send_array(emu, init3, ARRAY_SIZE(init3)/4);
 337
 338	EMU8000_HWCF4_WRITE(emu, 0);
 339	EMU8000_HWCF5_WRITE(emu, 0x83);
 340	EMU8000_HWCF6_WRITE(emu, 0x8000);
 341
 342	send_array(emu, init4, ARRAY_SIZE(init4)/4);
 343}
 344
 345
 346#define UNIQUE_ID1	0xa5b9
 347#define UNIQUE_ID2	0x9d53
 348
 349/*
 350 * Size the onboard memory.
 351 * This is written so as not to need arbitrary delays after the write. It
 352 * seems that the only way to do this is to use the one channel and keep
 353 * reallocating between read and write.
 354 */
 355static void
 356size_dram(struct snd_emu8000 *emu)
 357{
 358	int i, size;
 359
 360	if (emu->dram_checked)
 361		return;
 362
 363	size = 0;
 364
 365	/* write out a magic number */
 366	snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
 367	snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
 368	EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
 369	EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
 370	snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
 371	snd_emu8000_write_wait(emu);
 372
 373	/*
 374	 * Detect first 512 KiB.  If a write succeeds at the beginning of a
 375	 * 512 KiB page we assume that the whole page is there.
 376	 */
 377	EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
 378	EMU8000_SMLD_READ(emu); /* discard stale data  */
 379	if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
 380		goto skip_detect;   /* No RAM */
 381	snd_emu8000_read_wait(emu);
 382
 383	for (size = 512 * 1024; size < EMU8000_MAX_DRAM; size += 512 * 1024) {
 384
 385		/* Write a unique data on the test address.
 386		 * if the address is out of range, the data is written on
 387		 * 0x200000(=EMU8000_DRAM_OFFSET).  Then the id word is
 388		 * changed by this data.
 389		 */
 390		/*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
 391		EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
 392		EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
 393		snd_emu8000_write_wait(emu);
 394
 395		/*
 396		 * read the data on the just written DRAM address
 397		 * if not the same then we have reached the end of ram.
 398		 */
 399		/*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
 400		EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
 401		/*snd_emu8000_read_wait(emu);*/
 402		EMU8000_SMLD_READ(emu); /* discard stale data  */
 403		if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
 404			break; /* no memory at this address */
 405		snd_emu8000_read_wait(emu);
 406
 407		/*
 408		 * If it is the same it could be that the address just
 409		 * wraps back to the beginning; so check to see if the
 410		 * initial value has been overwritten.
 411		 */
 412		EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
 413		EMU8000_SMLD_READ(emu); /* discard stale data  */
 414		if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
 415			break; /* we must have wrapped around */
 416		snd_emu8000_read_wait(emu);
 417
 418		/* Otherwise, it's valid memory. */
 419	}
 420
 421skip_detect:
 422	/* wait until FULL bit in SMAxW register is false */
 423	for (i = 0; i < 10000; i++) {
 424		if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
 425			break;
 426		schedule_timeout_interruptible(1);
 427		if (signal_pending(current))
 428			break;
 429	}
 430	snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
 431	snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
 432
 433	pr_info("EMU8000 [0x%lx]: %d KiB on-board DRAM detected\n",
 434		    emu->port1, size/1024);
 435
 436	emu->mem_size = size;
 437	emu->dram_checked = 1;
 438}
 439
 440
 441/*
 442 * Initiailise the FM section.  You have to do this to use sample RAM
 443 * and therefore lose 2 voices.
 444 */
 445/*exported*/ void
 446snd_emu8000_init_fm(struct snd_emu8000 *emu)
 447{
 448	/* Initialize the last two channels for DRAM refresh and producing
 449	   the reverb and chorus effects for Yamaha OPL-3 synthesizer */
 450
 451	/* 31: FM left channel, 0xffffe0-0xffffe8 */
 452	EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
 453	EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
 454	EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
 455	EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
 456	EMU8000_CPF_WRITE(emu, 30, 0);
 457	EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
 458
 459	/* 32: FM right channel, 0xfffff0-0xfffff8 */
 460	EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
 461	EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
 462	EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
 463	EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
 464	EMU8000_CPF_WRITE(emu, 31, 0x8000);
 465	EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
 466
 467	snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
 468
 469	scoped_guard(spinlock_irqsave, &emu->reg_lock) {
 470		while (!(inw(EMU8000_PTR(emu)) & 0x1000))
 471			;
 472		while ((inw(EMU8000_PTR(emu)) & 0x1000))
 473			;
 474	}
 475	snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
 476	/* this is really odd part.. */
 477	outb(0x3C, EMU8000_PTR(emu));
 478	outb(0, EMU8000_DATA1(emu));
 479
 480	/* skew volume & cutoff */
 481	EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
 482	EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
 483}
 484
 485
 486/*
 487 * The main initialization routine.
 488 */
 489static void
 490snd_emu8000_init_hw(struct snd_emu8000 *emu)
 491{
 492	int i;
 493
 494	emu->last_reg = 0xffff; /* reset the last register index */
 495
 496	/* initialize hardware configuration */
 497	EMU8000_HWCF1_WRITE(emu, 0x0059);
 498	EMU8000_HWCF2_WRITE(emu, 0x0020);
 499
 500	/* disable audio; this seems to reduce a clicking noise a bit.. */
 501	EMU8000_HWCF3_WRITE(emu, 0);
 502
 503	/* initialize audio channels */
 504	init_audio(emu);
 505
 506	/* initialize DMA */
 507	init_dma(emu);
 508
 509	/* initialize init arrays */
 510	init_arrays(emu);
 511
 512	/*
 513	 * Initialize the FM section of the AWE32, this is needed
 514	 * for DRAM refresh as well
 515	 */
 516	snd_emu8000_init_fm(emu);
 517
 518	/* terminate all voices */
 519	for (i = 0; i < EMU8000_DRAM_VOICES; i++)
 520		EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
 521	
 522	/* check DRAM memory size */
 523	size_dram(emu);
 524
 525	/* enable audio */
 526	EMU8000_HWCF3_WRITE(emu, 0x4);
 527
 528	/* set equzlier, chorus and reverb modes */
 529	snd_emu8000_update_equalizer(emu);
 530	snd_emu8000_update_chorus_mode(emu);
 531	snd_emu8000_update_reverb_mode(emu);
 532}
 533
 534
 535/*----------------------------------------------------------------
 536 * Bass/Treble Equalizer
 537 *----------------------------------------------------------------*/
 538
 539static const unsigned short bass_parm[12][3] = {
 540	{0xD26A, 0xD36A, 0x0000}, /* -12 dB */
 541	{0xD25B, 0xD35B, 0x0000}, /*  -8 */
 542	{0xD24C, 0xD34C, 0x0000}, /*  -6 */
 543	{0xD23D, 0xD33D, 0x0000}, /*  -4 */
 544	{0xD21F, 0xD31F, 0x0000}, /*  -2 */
 545	{0xC208, 0xC308, 0x0001}, /*   0 (HW default) */
 546	{0xC219, 0xC319, 0x0001}, /*  +2 */
 547	{0xC22A, 0xC32A, 0x0001}, /*  +4 */
 548	{0xC24C, 0xC34C, 0x0001}, /*  +6 */
 549	{0xC26E, 0xC36E, 0x0001}, /*  +8 */
 550	{0xC248, 0xC384, 0x0002}, /* +10 */
 551	{0xC26A, 0xC36A, 0x0002}, /* +12 dB */
 552};
 553
 554static const unsigned short treble_parm[12][9] = {
 555	{0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
 556	{0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 557	{0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 558	{0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 559	{0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 560	{0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
 561	{0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
 562	{0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
 563	{0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
 564	{0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
 565	{0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
 566	{0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}  /* +12 dB */
 567};
 568
 569
 570/*
 571 * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
 572 */
 573/*exported*/ void
 574snd_emu8000_update_equalizer(struct snd_emu8000 *emu)
 575{
 576	unsigned short w;
 577	int bass = emu->bass_level;
 578	int treble = emu->treble_level;
 579
 580	if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
 581		return;
 582	EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
 583	EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
 584	EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
 585	EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
 586	EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
 587	EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
 588	EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
 589	EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
 590	EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
 591	EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
 592	w = bass_parm[bass][2] + treble_parm[treble][8];
 593	EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
 594	EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
 595}
 596
 597
 598/*----------------------------------------------------------------
 599 * Chorus mode control
 600 *----------------------------------------------------------------*/
 601
 602/*
 603 * chorus mode parameters
 604 */
 605#define SNDRV_EMU8000_CHORUS_1		0
 606#define	SNDRV_EMU8000_CHORUS_2		1
 607#define	SNDRV_EMU8000_CHORUS_3		2
 608#define	SNDRV_EMU8000_CHORUS_4		3
 609#define	SNDRV_EMU8000_CHORUS_FEEDBACK	4
 610#define	SNDRV_EMU8000_CHORUS_FLANGER	5
 611#define	SNDRV_EMU8000_CHORUS_SHORTDELAY	6
 612#define	SNDRV_EMU8000_CHORUS_SHORTDELAY2	7
 613#define SNDRV_EMU8000_CHORUS_PREDEFINED	8
 614/* user can define chorus modes up to 32 */
 615#define SNDRV_EMU8000_CHORUS_NUMBERS	32
 616
 617struct soundfont_chorus_fx {
 618	unsigned short feedback;	/* feedback level (0xE600-0xE6FF) */
 619	unsigned short delay_offset;	/* delay (0-0x0DA3) [1/44100 sec] */
 620	unsigned short lfo_depth;	/* LFO depth (0xBC00-0xBCFF) */
 621	unsigned int delay;	/* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
 622	unsigned int lfo_freq;		/* LFO freq LFO freq (0-0xFFFFFFFF) */
 623};
 624
 625/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
 626static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
 627static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
 628	{0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
 629	{0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
 630	{0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
 631	{0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
 632	{0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
 633	{0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
 634	{0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
 635	{0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
 636};
 637
 638/*exported*/ int
 639snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
 640{
 641	struct soundfont_chorus_fx rec;
 642	if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
 643		dev_warn(emu->card->dev, "invalid chorus mode %d for uploading\n", mode);
 644		return -EINVAL;
 645	}
 646	if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
 647		return -EFAULT;
 648	chorus_parm[mode] = rec;
 649	chorus_defined[mode] = 1;
 650	return 0;
 651}
 652
 653/*exported*/ void
 654snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu)
 655{
 656	int effect = emu->chorus_mode;
 657	if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
 658	    (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
 659		return;
 660	EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
 661	EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
 662	EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
 663	EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
 664	EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
 665	EMU8000_HWCF6_WRITE(emu, 0x8000);
 666	EMU8000_HWCF7_WRITE(emu, 0x0000);
 667}
 668
 669/*----------------------------------------------------------------
 670 * Reverb mode control
 671 *----------------------------------------------------------------*/
 672
 673/*
 674 * reverb mode parameters
 675 */
 676#define	SNDRV_EMU8000_REVERB_ROOM1	0
 677#define SNDRV_EMU8000_REVERB_ROOM2	1
 678#define	SNDRV_EMU8000_REVERB_ROOM3	2
 679#define	SNDRV_EMU8000_REVERB_HALL1	3
 680#define	SNDRV_EMU8000_REVERB_HALL2	4
 681#define	SNDRV_EMU8000_REVERB_PLATE	5
 682#define	SNDRV_EMU8000_REVERB_DELAY	6
 683#define	SNDRV_EMU8000_REVERB_PANNINGDELAY 7
 684#define SNDRV_EMU8000_REVERB_PREDEFINED	8
 685/* user can define reverb modes up to 32 */
 686#define SNDRV_EMU8000_REVERB_NUMBERS	32
 687
 688struct soundfont_reverb_fx {
 689	unsigned short parms[28];
 690};
 691
 692/* reverb mode settings; write the following 28 data of 16 bit length
 693 *   on the corresponding ports in the reverb_cmds array
 694 */
 695static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
 696static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
 697{{  /* room 1 */
 698	0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
 699	0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
 700	0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 701	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 702}},
 703{{  /* room 2 */
 704	0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 705	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
 706	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 707	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 708}},
 709{{  /* room 3 */
 710	0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 711	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
 712	0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
 713	0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
 714}},
 715{{  /* hall 1 */
 716	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 717	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
 718	0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
 719	0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
 720}},
 721{{  /* hall 2 */
 722	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
 723	0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
 724	0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 725	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 726}},
 727{{  /* plate */
 728	0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
 729	0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
 730	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 731	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 732}},
 733{{  /* delay */
 734	0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
 735	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
 736	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
 737	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
 738}},
 739{{  /* panning delay */
 740	0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
 741	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
 742	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
 743	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
 744}},
 745};
 746
 747enum { DATA1, DATA2 };
 748#define AWE_INIT1(c)	EMU8000_CMD(2,c), DATA1
 749#define AWE_INIT2(c)	EMU8000_CMD(2,c), DATA2
 750#define AWE_INIT3(c)	EMU8000_CMD(3,c), DATA1
 751#define AWE_INIT4(c)	EMU8000_CMD(3,c), DATA2
 752
 753static struct reverb_cmd_pair {
 754	unsigned short cmd, port;
 755} reverb_cmds[28] = {
 756  {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
 757  {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
 758  {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
 759  {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
 760  {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
 761  {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
 762  {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
 763};
 764
 765/*exported*/ int
 766snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
 767{
 768	struct soundfont_reverb_fx rec;
 769
 770	if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
 771		dev_warn(emu->card->dev, "invalid reverb mode %d for uploading\n", mode);
 772		return -EINVAL;
 773	}
 774	if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
 775		return -EFAULT;
 776	reverb_parm[mode] = rec;
 777	reverb_defined[mode] = 1;
 778	return 0;
 779}
 780
 781/*exported*/ void
 782snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu)
 783{
 784	int effect = emu->reverb_mode;
 785	int i;
 786
 787	if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
 788	    (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
 789		return;
 790	for (i = 0; i < 28; i++) {
 791		int port;
 792		if (reverb_cmds[i].port == DATA1)
 793			port = EMU8000_DATA1(emu);
 794		else
 795			port = EMU8000_DATA2(emu);
 796		snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
 797	}
 798}
 799
 800
 801/*----------------------------------------------------------------
 802 * mixer interface
 803 *----------------------------------------------------------------*/
 804
 805/*
 806 * bass/treble
 807 */
 808static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 809{
 810	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 811	uinfo->count = 1;
 812	uinfo->value.integer.min = 0;
 813	uinfo->value.integer.max = 11;
 814	return 0;
 815}
 816
 817static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 818{
 819	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 820	
 821	ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
 822	return 0;
 823}
 824
 825static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 826{
 827	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 828	int change;
 829	unsigned short val1;
 830	
 831	val1 = ucontrol->value.integer.value[0] % 12;
 832	scoped_guard(spinlock_irqsave, &emu->control_lock) {
 833		if (kcontrol->private_value) {
 834			change = val1 != emu->treble_level;
 835			emu->treble_level = val1;
 836		} else {
 837			change = val1 != emu->bass_level;
 838			emu->bass_level = val1;
 839		}
 840	}
 841	snd_emu8000_update_equalizer(emu);
 842	return change;
 843}
 844
 845static const struct snd_kcontrol_new mixer_bass_control =
 846{
 847	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 848	.name = "Synth Tone Control - Bass",
 849	.info = mixer_bass_treble_info,
 850	.get = mixer_bass_treble_get,
 851	.put = mixer_bass_treble_put,
 852	.private_value = 0,
 853};
 854
 855static const struct snd_kcontrol_new mixer_treble_control =
 856{
 857	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 858	.name = "Synth Tone Control - Treble",
 859	.info = mixer_bass_treble_info,
 860	.get = mixer_bass_treble_get,
 861	.put = mixer_bass_treble_put,
 862	.private_value = 1,
 863};
 864
 865/*
 866 * chorus/reverb mode
 867 */
 868static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 869{
 870	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 871	uinfo->count = 1;
 872	uinfo->value.integer.min = 0;
 873	uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
 874	return 0;
 875}
 876
 877static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 878{
 879	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 880	
 881	ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
 882	return 0;
 883}
 884
 885static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 886{
 887	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 888	int change;
 889	unsigned short val1;
 890	
 891	scoped_guard(spinlock_irqsave, &emu->control_lock) {
 892		if (kcontrol->private_value) {
 893			val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
 894			change = val1 != emu->chorus_mode;
 895			emu->chorus_mode = val1;
 896		} else {
 897			val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
 898			change = val1 != emu->reverb_mode;
 899			emu->reverb_mode = val1;
 900		}
 901	}
 902	if (change) {
 903		if (kcontrol->private_value)
 904			snd_emu8000_update_chorus_mode(emu);
 905		else
 906			snd_emu8000_update_reverb_mode(emu);
 907	}
 908	return change;
 909}
 910
 911static const struct snd_kcontrol_new mixer_chorus_mode_control =
 912{
 913	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 914	.name = "Chorus Mode",
 915	.info = mixer_chorus_reverb_info,
 916	.get = mixer_chorus_reverb_get,
 917	.put = mixer_chorus_reverb_put,
 918	.private_value = 1,
 919};
 920
 921static const struct snd_kcontrol_new mixer_reverb_mode_control =
 922{
 923	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 924	.name = "Reverb Mode",
 925	.info = mixer_chorus_reverb_info,
 926	.get = mixer_chorus_reverb_get,
 927	.put = mixer_chorus_reverb_put,
 928	.private_value = 0,
 929};
 930
 931/*
 932 * FM OPL3 chorus/reverb depth
 933 */
 934static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 935{
 936	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 937	uinfo->count = 1;
 938	uinfo->value.integer.min = 0;
 939	uinfo->value.integer.max = 255;
 940	return 0;
 941}
 942
 943static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 944{
 945	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 946	
 947	ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
 948	return 0;
 949}
 950
 951static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 952{
 953	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 954	int change;
 955	unsigned short val1;
 956	
 957	val1 = ucontrol->value.integer.value[0] % 256;
 958	scoped_guard(spinlock_irqsave, &emu->control_lock) {
 959		if (kcontrol->private_value) {
 960			change = val1 != emu->fm_chorus_depth;
 961			emu->fm_chorus_depth = val1;
 962		} else {
 963			change = val1 != emu->fm_reverb_depth;
 964			emu->fm_reverb_depth = val1;
 965		}
 966	}
 967	if (change)
 968		snd_emu8000_init_fm(emu);
 969	return change;
 970}
 971
 972static const struct snd_kcontrol_new mixer_fm_chorus_depth_control =
 973{
 974	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 975	.name = "FM Chorus Depth",
 976	.info = mixer_fm_depth_info,
 977	.get = mixer_fm_depth_get,
 978	.put = mixer_fm_depth_put,
 979	.private_value = 1,
 980};
 981
 982static const struct snd_kcontrol_new mixer_fm_reverb_depth_control =
 983{
 984	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 985	.name = "FM Reverb Depth",
 986	.info = mixer_fm_depth_info,
 987	.get = mixer_fm_depth_get,
 988	.put = mixer_fm_depth_put,
 989	.private_value = 0,
 990};
 991
 992
 993static const struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
 994	&mixer_bass_control,
 995	&mixer_treble_control,
 996	&mixer_chorus_mode_control,
 997	&mixer_reverb_mode_control,
 998	&mixer_fm_chorus_depth_control,
 999	&mixer_fm_reverb_depth_control,
1000};
1001
1002/*
1003 * create and attach mixer elements for WaveTable treble/bass controls
1004 */
1005static int
1006snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
1007{
1008	struct snd_kcontrol *kctl;
1009	int i, err = 0;
1010
1011	if (snd_BUG_ON(!emu || !card))
1012		return -EINVAL;
1013
1014	spin_lock_init(&emu->control_lock);
1015
1016	memset(emu->controls, 0, sizeof(emu->controls));
1017	for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1018		kctl = snd_ctl_new1(mixer_defs[i], emu);
1019		err = snd_ctl_add(card, kctl);
1020		if (err < 0)
1021			goto __error;
1022		emu->controls[i] = kctl;
1023	}
1024	return 0;
1025
1026__error:
1027	for (i = 0; i < EMU8000_NUM_CONTROLS; i++)
1028		snd_ctl_remove(card, emu->controls[i]);
1029	return err;
1030}
1031
1032/*
1033 * initialize and register emu8000 synth device.
1034 */
1035int
1036snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
1037		struct snd_seq_device **awe_ret)
1038{
1039	struct snd_seq_device *awe;
1040	struct snd_emu8000 *hw;
1041	int err;
1042
1043	if (awe_ret)
1044		*awe_ret = NULL;
1045
1046	if (seq_ports <= 0)
1047		return 0;
1048
1049	hw = devm_kzalloc(card->dev, sizeof(*hw), GFP_KERNEL);
1050	if (hw == NULL)
1051		return -ENOMEM;
1052	spin_lock_init(&hw->reg_lock);
1053	hw->index = index;
1054	hw->port1 = port;
1055	hw->port2 = port + 0x400;
1056	hw->port3 = port + 0x800;
1057	if (!devm_request_region(card->dev, hw->port1, 4, "Emu8000-1") ||
1058	    !devm_request_region(card->dev, hw->port2, 4, "Emu8000-2") ||
1059	    !devm_request_region(card->dev, hw->port3, 4, "Emu8000-3")) {
1060		dev_err(card->dev, "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n",
1061			hw->port1, hw->port2, hw->port3);
1062		return -EBUSY;
1063	}
1064	hw->mem_size = 0;
1065	hw->card = card;
1066	hw->seq_ports = seq_ports;
1067	hw->bass_level = 5;
1068	hw->treble_level = 9;
1069	hw->chorus_mode = 2;
1070	hw->reverb_mode = 4;
1071	hw->fm_chorus_depth = 0;
1072	hw->fm_reverb_depth = 0;
1073
1074	if (snd_emu8000_detect(hw) < 0)
1075		return -ENODEV;
1076
1077	snd_emu8000_init_hw(hw);
1078	err = snd_emu8000_create_mixer(card, hw);
1079	if (err < 0)
1080		return err;
1081#if IS_ENABLED(CONFIG_SND_SEQUENCER)
1082	if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1083			       sizeof(struct snd_emu8000*), &awe) >= 0) {
1084		strscpy(awe->name, "EMU-8000");
1085		*(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1086	}
1087#else
1088	awe = NULL;
1089#endif
1090	if (awe_ret)
1091		*awe_ret = awe;
1092
1093	return 0;
1094}
1095
1096
1097/*
1098 * exported stuff
1099 */
1100
1101EXPORT_SYMBOL(snd_emu8000_poke);
1102EXPORT_SYMBOL(snd_emu8000_peek);
1103EXPORT_SYMBOL(snd_emu8000_poke_dw);
1104EXPORT_SYMBOL(snd_emu8000_peek_dw);
1105EXPORT_SYMBOL(snd_emu8000_dma_chan);
1106EXPORT_SYMBOL(snd_emu8000_init_fm);
1107EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1108EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1109EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1110EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1111EXPORT_SYMBOL(snd_emu8000_update_equalizer);
~/ Read-only file preview.