linux/sound/isa/opti9xx/opti92x-ad1848.c

// 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 <[email protected]>

    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();
MODULE_LICENSE();
#ifdef OPTi93X
MODULE_DESCRIPTION("OPTi93X");
#else	/* OPTi93X */
#ifdef CS4231
MODULE_DESCRIPTION("OPTi92X - CS4231");
#else	/* CS4231 */
MODULE_DESCRIPTION();
#endif	/* CS4231 */
#endif	/* OPTi93X */

static int index =;	/* Index 0-MAX */
static char *id =;		/* ID for this card */
//static bool enable = SNDRV_DEFAULT_ENABLE1;	/* Enable this card */
#ifdef CONFIG_PNP
static bool isapnp =;			/* Enable ISA PnP detection */
#endif
static long port =; 	/* 0x530,0xe80,0xf40,0x604 */
static long mpu_port =;	/* 0x300,0x310,0x320,0x330 */
static long fm_port =;	/* 0x388 */
static int irq =;		/* 5,7,9,10,11 */
static int mpu_irq =;	/* 5,7,9,10 */
static int 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();
module_param(id, charp, 0444);
MODULE_PARM_DESC();
//module_param(enable, bool, 0444);
//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
#ifdef CONFIG_PNP
module_param(isapnp, bool, 0444);
MODULE_PARM_DESC();
#endif
module_param_hw(port, long, ioport, 0444);
MODULE_PARM_DESC();
module_param_hw(mpu_port, long, ioport, 0444);
MODULE_PARM_DESC();
module_param_hw(fm_port, long, ioport, 0444);
MODULE_PARM_DESC();
module_param_hw(irq, int, irq, 0444);
MODULE_PARM_DESC();
module_param_hw(mpu_irq, int, irq, 0444);
MODULE_PARM_DESC();
module_param_hw(dma1, int, dma, 0444);
MODULE_PARM_DESC();
#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
#define OPTi9XX_HW_82C929
#define OPTi9XX_HW_82C924
#define OPTi9XX_HW_82C925
#define OPTi9XX_HW_82C930
#define OPTi9XX_HW_82C931
#define OPTi9XX_HW_82C933
#define OPTi9XX_HW_LAST

#define OPTi9XX_MC_REG(n)

#ifdef OPTi93X

#define OPTi93X_STATUS
#define OPTi93X_PORT

#define OPTi93X_IRQ_PLAYBACK
#define OPTi93X_IRQ_CAPTURE

#endif /* OPTi93X */

struct snd_opti9xx {};

static int snd_opti9xx_pnp_is_probed;

#ifdef CONFIG_PNP

static const struct pnp_card_device_id snd_opti9xx_pnpids[] =;

MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);

#endif	/* CONFIG_PNP */

#define DEV_NAME

static const char * const snd_opti9xx_names[] =;

static int snd_opti9xx_init(struct snd_opti9xx *chip,
			    unsigned short hardware)
{}

static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
				      unsigned char reg)
{}

static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
			      unsigned char value)
{}


static inline void snd_opti9xx_write_mask(struct snd_opti9xx *chip,
		unsigned char reg, unsigned char value, unsigned char mask)
{}

static int snd_opti9xx_configure(struct snd_opti9xx *chip,
					   long port,
					   int irq, int dma1, int dma2,
					   long mpu_port, int mpu_irq)
{}

#ifdef OPTi93X

static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_step, -9300, 300, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_4bit_12db_max, -3300, 300, 0);

static const struct snd_kcontrol_new snd_opti93x_controls[] = {
WSS_DOUBLE("Master Playback Switch", 0,
		OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
WSS_DOUBLE_TLV("Master Playback Volume", 0,
		OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1,
		db_scale_5bit_3db_step),
WSS_DOUBLE_TLV("PCM Playback Volume", 0,
		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1,
		db_scale_5bit),
WSS_DOUBLE_TLV("FM Playback Volume", 0,
		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1,
		db_scale_4bit_12db_max),
WSS_DOUBLE("Line Playback Switch", 0,
		CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
WSS_DOUBLE_TLV("Line Playback Volume", 0,
		CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1,
		db_scale_4bit_12db_max),
WSS_DOUBLE("Mic Playback Switch", 0,
		OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
WSS_DOUBLE_TLV("Mic Playback Volume", 0,
		OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1,
		db_scale_4bit_12db_max),
WSS_DOUBLE_TLV("CD Playback Volume", 0,
		CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1,
		db_scale_4bit_12db_max),
WSS_DOUBLE("Aux Playback Switch", 0,
		OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
WSS_DOUBLE_TLV("Aux Playback Volume", 0,
		OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1,
		db_scale_4bit_12db_max),
};

static int snd_opti93x_mixer(struct snd_wss *chip)
{
	struct snd_card *card;
	unsigned int idx;
	struct snd_ctl_elem_id id1, id2;
	int err;

	if (snd_BUG_ON(!chip || !chip->pcm))
		return -EINVAL;

	card = chip->card;

	strcpy(card->mixername, chip->pcm->name);

	memset(&id1, 0, sizeof(id1));
	memset(&id2, 0, sizeof(id2));
	id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
	/* reassign AUX0 switch to CD */
	strcpy(id1.name, "Aux Playback Switch");
	strcpy(id2.name, "CD Playback Switch");
	err = snd_ctl_rename_id(card, &id1, &id2);
	if (err < 0) {
		snd_printk(KERN_ERR "Cannot rename opti93x control\n");
		return err;
	}
	/* reassign AUX1 switch to FM */
	strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
	strcpy(id2.name, "FM Playback Switch");
	err = snd_ctl_rename_id(card, &id1, &id2);
	if (err < 0) {
		snd_printk(KERN_ERR "Cannot rename opti93x control\n");
		return err;
	}
	/* remove AUX1 volume */
	strcpy(id1.name, "Aux Playback Volume"); id1.index = 1;
	snd_ctl_remove_id(card, &id1);

	/* Replace WSS volume controls with OPTi93x volume controls */
	id1.index = 0;
	for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
		strcpy(id1.name, snd_opti93x_controls[idx].name);
		snd_ctl_remove_id(card, &id1);

		err = snd_ctl_add(card,
				snd_ctl_new1(&snd_opti93x_controls[idx], chip));
		if (err < 0)
			return err;
	}
	return 0;
}

static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
{
	struct snd_opti9xx *chip = dev_id;
	struct snd_wss *codec = chip->codec;
	unsigned char status;

	if (!codec)
		return IRQ_HANDLED;

	status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
	if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
		snd_pcm_period_elapsed(codec->playback_substream);
	if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
		snd_wss_overrange(codec);
		snd_pcm_period_elapsed(codec->capture_substream);
	}
	outb(0x00, OPTi93X_PORT(codec, STATUS));
	return IRQ_HANDLED;
}

#endif /* OPTi93X */

static int snd_opti9xx_read_check(struct snd_card *card,
				  struct snd_opti9xx *chip)
{}

static int snd_card_opti9xx_detect(struct snd_card *card,
				   struct snd_opti9xx *chip)
{}

#ifdef CONFIG_PNP
static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
				struct pnp_card_link *card,
				const struct pnp_card_device_id *pid)
{}
#endif	/* CONFIG_PNP */

static int snd_opti9xx_probe(struct snd_card *card)
{}

static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp)
{}

static int snd_opti9xx_isa_match(struct device *devptr,
				 unsigned int dev)
{}

static int snd_opti9xx_isa_probe(struct device *devptr,
				 unsigned int dev)
{}

#ifdef CONFIG_PM
static int snd_opti9xx_suspend(struct snd_card *card)
{}

static int snd_opti9xx_resume(struct snd_card *card)
{}

static int snd_opti9xx_isa_suspend(struct device *dev, unsigned int n,
				   pm_message_t state)
{}

static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
{}
#endif

static struct isa_driver snd_opti9xx_driver =;

#ifdef CONFIG_PNP
static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
				 const struct pnp_card_device_id *pid)
{}

static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
{}

#ifdef CONFIG_PM
static int snd_opti9xx_pnp_suspend(struct pnp_card_link *pcard,
				   pm_message_t state)
{}

static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard)
{}
#endif

static struct pnp_card_driver opti9xx_pnpc_driver =;
#endif

#ifdef OPTi93X
#define CHIP_NAME
#else
#define CHIP_NAME
#endif

static int __init alsa_card_opti9xx_init(void)
{}

static void __exit alsa_card_opti9xx_exit(void)
{}

module_init()
module_exit()