linux/sound/isa/sscape.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *   Low-level ALSA driver for the ENSONIQ SoundScape
 *   Copyright (c) by Chris Rankin
 *
 *   This driver was written in part using information obtained from
 *   the OSS/Free SoundScape driver, written by Hannu Savolainen.
 */

#include <linux/init.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/isa.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/pnp.h>
#include <linux/spinlock.h>
#include <linux/module.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/mpu401.h>
#include <sound/initval.h>


MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();
MODULE_FIRMWARE();

static int index[SNDRV_CARDS] =;
static char* id[SNDRV_CARDS] =;
static long port[SNDRV_CARDS] =;
static long wss_port[SNDRV_CARDS] =;
static int irq[SNDRV_CARDS] =;
static int mpu_irq[SNDRV_CARDS] =;
static int dma[SNDRV_CARDS] =;
static int dma2[SNDRV_CARDS] =;
static bool joystick[SNDRV_CARDS];

module_param_array();
MODULE_PARM_DESC();

module_param_array();
MODULE_PARM_DESC();

module_param_hw_array(port, long, ioport, NULL, 0444);
MODULE_PARM_DESC();

module_param_hw_array(wss_port, long, ioport, NULL, 0444);
MODULE_PARM_DESC();

module_param_hw_array(irq, int, irq, NULL, 0444);
MODULE_PARM_DESC();

module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
MODULE_PARM_DESC();

module_param_hw_array(dma, int, dma, NULL, 0444);
MODULE_PARM_DESC();

module_param_hw_array(dma2, int, dma, NULL, 0444);
MODULE_PARM_DESC();

module_param_array();
MODULE_PARM_DESC();

#ifdef CONFIG_PNP
static int isa_registered;
static int pnp_registered;

static const struct pnp_card_device_id sscape_pnpids[] =;

MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
#endif


#define HOST_CTRL_IO(i)
#define HOST_DATA_IO(i)
#define ODIE_ADDR_IO(i)
#define ODIE_DATA_IO(i)
#define CODEC_IO(i)

#define IC_ODIE
#define IC_OPUS

#define RX_READY
#define TX_READY

#define CMD_ACK
#define CMD_SET_MIDI_VOL
#define CMD_GET_MIDI_VOL
#define CMD_XXX_MIDI_VOL
#define CMD_SET_EXTMIDI
#define CMD_GET_EXTMIDI
#define CMD_SET_MT32
#define CMD_GET_MT32

enum GA_REG {};

#define DMA_8BIT


enum card_type {};

struct soundscape {};

#define INVALID_IRQ


static inline struct soundscape *get_card_soundscape(struct snd_card *c)
{}

/*
 * Allocates some kernel memory that we can use for DMA.
 * I think this means that the memory has to map to
 * contiguous pages of physical memory.
 */
static struct snd_dma_buffer *get_dmabuf(struct soundscape *s,
					 struct snd_dma_buffer *buf,
					 unsigned long size)
{}

/*
 * Release the DMA-able kernel memory ...
 */
static void free_dmabuf(struct snd_dma_buffer *buf)
{}

/*
 * This function writes to the SoundScape's control registers,
 * but doesn't do any locking. It's up to the caller to do that.
 * This is why this function is "unsafe" ...
 */
static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg,
				       unsigned char val)
{}

/*
 * Write to the SoundScape's control registers, and do the
 * necessary locking ...
 */
static void sscape_write(struct soundscape *s, enum GA_REG reg,
			 unsigned char val)
{}

/*
 * Read from the SoundScape's control registers, but leave any
 * locking to the caller. This is why the function is "unsafe" ...
 */
static inline unsigned char sscape_read_unsafe(unsigned io_base,
					       enum GA_REG reg)
{}

/*
 * Puts the SoundScape into "host" mode, as compared to "MIDI" mode
 */
static inline void set_host_mode_unsafe(unsigned io_base)
{}

/*
 * Puts the SoundScape into "MIDI" mode, as compared to "host" mode
 */
static inline void set_midi_mode_unsafe(unsigned io_base)
{}

/*
 * Read the SoundScape's host-mode control register, but leave
 * any locking issues to the caller ...
 */
static inline int host_read_unsafe(unsigned io_base)
{}

/*
 * Read the SoundScape's host-mode control register, performing
 * a limited amount of busy-waiting if the register isn't ready.
 * Also leaves all locking-issues to the caller ...
 */
static int host_read_ctrl_unsafe(unsigned io_base, unsigned timeout)
{}

/*
 * Write to the SoundScape's host-mode control registers, but
 * leave any locking issues to the caller ...
 */
static inline int host_write_unsafe(unsigned io_base, unsigned char data)
{}

/*
 * Write to the SoundScape's host-mode control registers, performing
 * a limited amount of busy-waiting if the register isn't ready.
 * Also leaves all locking-issues to the caller ...
 */
static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
				  unsigned timeout)
{}


/*
 * Check that the MIDI subsystem is operational. If it isn't,
 * then we will hang the computer if we try to use it ...
 *
 * NOTE: This check is based upon observation, not documentation.
 */
static inline int verify_mpu401(const struct snd_mpu401 *mpu)
{}

/*
 * This is apparently the standard way to initialise an MPU-401
 */
static inline void initialise_mpu401(const struct snd_mpu401 *mpu)
{}

/*
 * Tell the SoundScape to activate the AD1845 chip (I think).
 * The AD1845 detection fails if we *don't* do this, so I
 * think that this is a good idea ...
 */
static void activate_ad1845_unsafe(unsigned io_base)
{}

/*
 * Tell the SoundScape to begin a DMA transfer using the given channel.
 * All locking issues are left to the caller.
 */
static void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
{}

/*
 * Wait for a DMA transfer to complete. This is a "limited busy-wait",
 * and all locking issues are left to the caller.
 */
static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg,
				  unsigned timeout)
{}

/*
 * Wait for the On-Board Processor to return its start-up
 * acknowledgement sequence. This wait is too long for
 * us to perform "busy-waiting", and so we must sleep.
 * This in turn means that we must not be holding any
 * spinlocks when we call this function.
 */
static int obp_startup_ack(struct soundscape *s, unsigned timeout)
{}

/*
 * Wait for the host to return its start-up acknowledgement
 * sequence. This wait is too long for us to perform
 * "busy-waiting", and so we must sleep. This in turn means
 * that we must not be holding any spinlocks when we call
 * this function.
 */
static int host_startup_ack(struct soundscape *s, unsigned timeout)
{}

/*
 * Upload a byte-stream into the SoundScape using DMA channel A.
 */
static int upload_dma_data(struct soundscape *s, const unsigned char *data,
			   size_t size)
{}

/*
 * Upload the bootblock(?) into the SoundScape. The only
 * purpose of this block of code seems to be to tell
 * us which version of the microcode we should be using.
 */
static int sscape_upload_bootblock(struct snd_card *card)
{}

/*
 * Upload the microcode into the SoundScape.
 */
static int sscape_upload_microcode(struct snd_card *card, int version)
{}

/*
 * Mixer control for the SoundScape's MIDI device.
 */
static int sscape_midi_info(struct snd_kcontrol *ctl,
			    struct snd_ctl_elem_info *uinfo)
{}

static int sscape_midi_get(struct snd_kcontrol *kctl,
			   struct snd_ctl_elem_value *uctl)
{}

static int sscape_midi_put(struct snd_kcontrol *kctl,
			   struct snd_ctl_elem_value *uctl)
{}

static const struct snd_kcontrol_new midi_mixer_ctl =;

/*
 * The SoundScape can use two IRQs from a possible set of four.
 * These IRQs are encoded as bit patterns so that they can be
 * written to the control registers.
 */
static unsigned get_irq_config(int sscape_type, int irq)
{}

/*
 * Perform certain arcane port-checks to see whether there
 * is a SoundScape board lurking behind the given ports.
 */
static int detect_sscape(struct soundscape *s, long wss_io)
{}

/*
 * ALSA callback function, called when attempting to open the MIDI device.
 * Check that the MIDI firmware has been loaded, because we don't want
 * to crash the machine. Also check that someone isn't using the hardware
 * IOCTL device.
 */
static int mpu401_open(struct snd_mpu401 *mpu)
{}

/*
 * Initialise an MPU-401 subdevice for MIDI support on the SoundScape.
 */
static int create_mpu401(struct snd_card *card, int devnum,
			 unsigned long port, int irq)
{}


/*
 * Create an AD1845 PCM subdevice on the SoundScape. The AD1845
 * is very much like a CS4231, with a few extra bits. We will
 * try to support at least some of the extra bits by overriding
 * some of the CS4231 callback.
 */
static int create_ad1845(struct snd_card *card, unsigned port,
			 int irq, int dma1, int dma2)
{}


/*
 * Create an ALSA soundcard entry for the SoundScape, using
 * the given list of port, IRQ and DMA resources.
 */
static int create_sscape(int dev, struct snd_card *card)
{}


static int snd_sscape_match(struct device *pdev, unsigned int i)
{}

static int snd_sscape_probe(struct device *pdev, unsigned int dev)
{}

#define DEV_NAME

static struct isa_driver snd_sscape_driver =;

#ifdef CONFIG_PNP
static inline int get_next_autoindex(int i)
{}


static int sscape_pnp_detect(struct pnp_card_link *pcard,
			     const struct pnp_card_device_id *pid)
{}

static struct pnp_card_driver sscape_pnpc_driver =;

#endif /* CONFIG_PNP */

static int __init sscape_init(void)
{}

static void __exit sscape_exit(void)
{}

module_init();
module_exit(sscape_exit);