// SPDX-License-Identifier: GPL-2.0-or-later
/*
card-opti92x-ad1848.c - driver for OPTi 82c92x based soundcards.
Copyright (C) 1998-2000 by Massimo Piccioni <dafastidio@libero.it>
Part of this code was developed at the Italian Ministry of Air Defence,
Sixth Division (oh, che pace ...), Rome.
Thanks to Maria Grazia Pollarini, Salvatore Vassallo.
*/
#include <linux/init.h>
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/delay.h>
#include <linux/pnp.h>
#include <linux/module.h>
#include <linux/io.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/tlv.h>
#include <sound/wss.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
#ifndef OPTi93X
#include <sound/opl4.h>
#endif
#define SNDRV_LEGACY_FIND_FREE_IOPORT
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
MODULE_LICENSE("GPL");
#ifdef OPTi93X
MODULE_DESCRIPTION("OPTi93X");
MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}");
#else /* OPTi93X */
#ifdef CS4231
MODULE_DESCRIPTION("OPTi92X - CS4231");
MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)},"
"{OPTi,82C925 (CS4231)}}");
#else /* CS4231 */
MODULE_DESCRIPTION("OPTi92X - AD1848");
MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
"{OPTi,82C925 (AD1848)},"
"{OAK,Mozart}}");
#endif /* CS4231 */
#endif /* OPTi93X */
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
//static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
#ifdef CONFIG_PNP
static bool isapnp = true; /* Enable ISA PnP detection */
#endif
static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */
static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */
static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */
static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */
static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */
static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
#if defined(CS4231) || defined(OPTi93X)
static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
#endif /* CS4231 || OPTi93X */
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard.");
module_param(id, charp, 0444);
MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
//module_param(enable, bool, 0444);
//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
#ifdef CONFIG_PNP
module_param(isapnp, bool, 0444);
MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
#endif
module_param_hw(port, long, ioport, 0444);
MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
module_param_hw(mpu_port, long, ioport, 0444);
MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
module_param_hw(fm_port, long, ioport, 0444);
MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
module_param_hw(irq, int, irq, 0444);
MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
module_param_hw(mpu_irq, int, irq, 0444);
MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
module_param_hw(dma1, int, dma, 0444);
MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
#if defined(CS4231) || defined(OPTi93X)
module_param_hw(dma2, int, dma, 0444);
MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
#endif /* CS4231 || OPTi93X */
#define OPTi9XX_HW_82C928 1
#define OPTi9XX_HW_82C929 2
#define OPTi9XX_HW_82C924 3
#define OPTi9XX_HW_82C925 4
#define OPTi9XX_HW_82C930 5
#define OPTi9XX_HW_82C931 6
#define OPTi9XX_HW_82C933 7
#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933
#define OPTi9XX_MC_REG(n) n
#ifdef OPTi93X
#define OPTi93X_STATUS 0x02
#define OPTi93X_PORT(chip, r) ((chip)->port + OPTi93X_##r)
#define OPTi93X_IRQ_PLAYBACK 0x04
#define OPTi93X_IRQ_CAPTURE 0x08
#endif /* OPTi93X */
struct snd_opti9xx {
unsigned short hardware;
unsigned char password;
char name[7];
unsigned long mc_base